Home > Back-end >  Hibernate 5 and JPA: select table without his children but maintain persistence on save
Hibernate 5 and JPA: select table without his children but maintain persistence on save

Time:04-11

I have two models: Ordine and DettaglioOrdine. I would like that, when I save an object of type "Ordine", hibernate also save his child "DettaglioOrdine" (and this works). But, if I do a select query, the query is very very slow because hibernate retrieve also DettaglioOrdine. So, I would like the "Ordine" object without "DettaglioOrdine" object.

"Ordine" model:

@Entity
@Table(name="ordini")
@NamedQuery(name="Ordine.findAll", query="SELECT o FROM Ordine o")
public class Ordine extends DataObject<Integer> {
    private static final long serialVersionUID = 1L;
    private Integer id;
[...]
    private List<Dettagliordine> dettagliordine;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    //bi-directional many-to-one association to Dettagliordine
    @Column(insertable = true, updatable = true)
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="ordine")
    public List<Dettagliordine> getDettagliordine() {
        return this.dettagliordine;
    }

    public void setDettagliordine(List<Dettagliordine> dettagliordine) {
        this.dettagliordine = dettagliordine;
    }

    public Dettagliordine addDettagliordine(Dettagliordine dettaglioordine) {
        dettaglioordine.setOrdine(this);
        this.dettagliordine.add(dettaglioordine);

        return dettaglioordine;
    }

    public Dettagliordine removeDettagliordine(Dettagliordine dettagliordine) {
        dettagliordine.setOrdine(null);
        this.dettagliordine.remove(dettagliordine);
        
        return dettagliordine;
    

    }
}

DettaglioOrdine Model:

@Entity
@Table(name="dettagliordine")
@NamedQuery(name="Dettagliordine.findAll", query="SELECT d FROM Dettagliordine d")
public class Dettagliordine extends DataObject<Integer> {
    private static final long serialVersionUID = 1L;
    private Integer id;
    
        [...]
        
    public Dettagliordine() {
    }
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    [...]
    
    //bi-directional many-to-one association to Ordini
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="idOrdine", nullable=false)
    public Ordine getOrdine() {
        return this.ordine;
    }
    public void setOrdine(Ordine ordine) {
        this.ordine = ordine;
    }
}

And this is my query:

SessionFactory sessionFactory = getSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        List<OrdineDTO> result = null;
        try{
            String hql = "select d.ordine from Dettagliordine d "
                      "group by d.ordine.id";
            Query<Ordine> query = session.createQuery(hql,Ordine.class);
            List<Ordine> res = query.getResultList();
            result = new OrdineDMO().unmarshall(res);
        }catch (DMOException e) {
            e.printStackTrace();
        }

CodePudding user response:

Add optional=false in @OneTOMany annotation of Ordine class. this might work.

optional=false is a runtime instruction. The primary functional thing it does is related to Lazy Loading. You can't lazy load a non-collection mapped entity unless you remember to set optional=false (because Hibernate doesn't know if there should be a proxy there or a null, unless you tell it nulls are impossible, so it can generate a proxy.)

CodePudding user response:

It is not Hibernate. You have fetch=FetchType.LAZY for dettagliordine. Hibernate doesn't have to fetch the lazy association with the parent.

The problem can be here

result = new OrdineDMO().unmarshall(res);

if the code inside unmarshall() method touches dettagliordine or invoke a method, that differs from get, set methods (like toString() method), Hibernate will fetch dettagliordine association.

You can enable Hibernate logging and debug the code. You will see when fetching actually happens. Also keep in mind, if you debug persistent classes, the debugger can cause invoking of toString() method and the association will be fetched too.

Better to move this line outside session/@Transactional block of code.

result = new OrdineDMO().unmarshall(res);

You will have LazyInitializationExcepton, with any unwanted access to lazy associations.

  • Related