How to Speed ​​Up Hibernate DML Instructions for One-to-Many Associations

I am trying to optimize a hibernation application, and one of the biggest problems I have encountered with Hibernates performance is its tendency to execute n + 1 queries for a simple crud operation with child objects. I was able to prevent n + 1 requests for selecting operations using @Fetch(FetchMode.JOIN)for the child object (many-one side), but this does not affect update / insert / delete requests. The following is an example of relevant objects and properties:

// parent entity for Mean and Covariance entities
@Entity
@DynamicInsert
@Table(name = "belief")
public class Belief implements Serializable, Cloneable {

    // surrogate key
    @Id
    @GeneratedValue
    @Column(name = "belief_id", unique = true, insertable = false, updatable = false)
    private Integer id;

    // other properties...

    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    @OneToMany(mappedBy = "pk.beliefId", orphanRemoval = true, fetch = FetchType.LAZY)
    private List<Mean> means = new ArrayList<>();

    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    @OneToMany(mappedBy = "pk.beliefId", orphanRemoval = true, fetch = FetchType.LAZY)
    private List<Covariance> covariances = new ArrayList<>();

}

@Entity
@DynamicInsert
@Table(name = "mean")
public class Mean implements Serializable, Cloneable {

    // composite key
    @EmbeddedId
    private MeanPK pk = new MeanPK(this);

    @Fetch(FetchMode.JOIN)
    @ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
    @JoinColumn(name = "belief_id", insertable = false, nullable = false, updatable = false)
    private Belief belief;

    // other properties...
}

@Entity
@DynamicInsert
@Table(name = "covariance")
public class Covariance implements Serializable, Cloneable {

    // composite key
    @EmbeddedId
    private CovariancePK pk = new CovariancePK(this);

    @Fetch(FetchMode.JOIN)
    @ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
    @JoinColumn(name = "belief_id", insertable = false, nullable = false, updatable = false)
    private Belief belief;

    // other properties...
}

So, when I execute session.delete(belief);, the logs show that for each covariance a separate delete instruction is executed and means that the object of faith can be referenced. Here is an example log:

Hibernate: select belief0_.belief_id as belief_i1_0_0_, belief0_.after_comb as after_co2_0_0_, belief0_.description as descript3_0_0_, belief0_.name as name4_0_0_, belief0_.project_id as project_7_0_0_, belief0_.type as type5_0_0_, belief0_.version as version6_0_0_ from belief belief0_ where belief0_.belief_id=?
Hibernate: select covariance0_.belief_id as belief_i1_0_0_, covariance0_.belief_id as belief_i1_1_0_, covariance0_.col_variable_id as col_vari2_1_0_, covariance0_.row_variable_id as row_vari3_1_0_, covariance0_.belief_id as belief_i1_1_1_, covariance0_.col_variable_id as col_vari2_1_1_, covariance0_.row_variable_id as row_vari3_1_1_, covariance0_.variance as variance4_1_1_, covariance0_.version as version5_1_1_, variable1_.variable_id as variable1_5_2_, variable1_.definition as definiti2_5_2_, variable1_.description as descript3_5_2_, variable1_.name as name4_5_2_, variable1_.project_id as project_6_5_2_, variable1_.version as version5_5_2_, variable2_.variable_id as variable1_5_3_, variable2_.definition as definiti2_5_3_, variable2_.description as descript3_5_3_, variable2_.name as name4_5_3_, variable2_.project_id as project_6_5_3_, variable2_.version as version5_5_3_ from covariance covariance0_ inner join variable variable1_ on covariance0_.col_variable_id=variable1_.variable_id inner join variable variable2_ on covariance0_.row_variable_id=variable2_.variable_id where covariance0_.belief_id=?
Hibernate: select means0_.belief_id as belief_i1_0_0_, means0_.belief_id as belief_i1_2_0_, means0_.variable_id as variable2_2_0_, means0_.belief_id as belief_i1_2_1_, means0_.variable_id as variable2_2_1_, means0_.mean as mean3_2_1_, means0_.swept as swept4_2_1_, means0_.version as version5_2_1_, variable1_.variable_id as variable1_5_2_, variable1_.definition as definiti2_5_2_, variable1_.description as descript3_5_2_, variable1_.name as name4_5_2_, variable1_.project_id as project_6_5_2_, variable1_.version as version5_5_2_ from mean means0_ inner join variable variable1_ on means0_.variable_id=variable1_.variable_id where means0_.belief_id=?
Hibernate: delete from covariance where belief_id=? and col_variable_id=? and row_variable_id=? and version=?
Hibernate: delete from covariance where belief_id=? and col_variable_id=? and row_variable_id=? and version=?
Hibernate: delete from mean where belief_id=? and variable_id=? and version=?
Hibernate: delete from mean where belief_id=? and variable_id=? and version=?
Hibernate: delete from mean where belief_id=? and variable_id=? and version=?
Hibernate: delete from mean where belief_id=? and variable_id=? and version=?
Hibernate: delete from mean where belief_id=? and variable_id=? and version=?
Hibernate: delete from belief where belief_id=? and version=?

n + 1, select, //. - , ? !

+4
2

Hibernate DML, DELETE , .

EAGER, . LAZY, JOIN FETCH -.

:

, , UPDATE/DELETE HQL/JPQL.

+1

, Hibernate OR-Mapping.

FetchType.Lazy OneToMany, . FetchType.Eager n + 1 . ( , hibernate jpa, , ). , ? , , , . , , , . , .

!!! !!!

, , , . , , , . , .

  • - . ? , , .
  • EmbeddedId, ? , - .
  • , JoinColumn .. , .
0

All Articles