When I update my parent class, hibernate selects all its child before triggering the update. This only happens when we added new children that are not persistent in the database yet. Hibernate selects those children one by one, which is very... very slow.
Batching is already enabled and working for normal inserts, updates and removals. I gave the child a version, which hibernates ignores somehow.
select * from identity...
select * from identity...
select * from identity...
select * from identity...
insert .... into identity...
update chunk set ....
Is there a way to either make hibernate batch those selects or to implement some other mechanic in which hibernate simply checks the added child if its new without selecting it from the database first?
I basically want to get rid of those "one by one" selects. Would be glad for any help I can get.
When I update chunk which contains multiple identities that are not yet in the database ( inChunk )... it tries to determine if they are in the database which results in one select for each child to filter those children that are need to get inserted... how do I prevent those many selects? I still want to keep the cascading.
@Entity
@Access(AccessType.FIELD)
@SQLInsert(sql = "insert into identity(tag, typeID, id, version) values(?,?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id), tag = values(tag), typeID = values(typeID), version = values(version)")
@SelectBeforeUpdate(value = false)
public class Identity extends Component {
@Id public long id;
public String tag;
public String typeID;
@Version public long version;
}
@Entity
@Table(name = "chunk", uniqueConstraints = {@UniqueConstraint(columnNames={"x", "y"})}, indexes = {@Index(columnList = "x,y")})
@Access(value = AccessType.FIELD)
@SelectBeforeUpdate(false)
public class Chunk extends HibernateComponent {
public int x;
public int y;
public Date createdOn;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Fetch(FetchMode.JOIN)
@BatchSize(size = 50)
public Set<Identity> inChunk = new LinkedHashSet<>();
}
Unidirectional one-to-many association - is not good practice. I would recommend to define the many-to-one association in the Identity
class, then add the mappedBy
attribute to the @OneToMany
annotation on the inChunk
field, and then fetch Chunk.inChunk
association before add new children.
@Entity
@Access(AccessType.FIELD)
@SQLInsert(sql = "insert into identity(tag, typeID, id, version) values(?,?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id), tag = values(tag), typeID = values(typeID), version = values(version)")
@SelectBeforeUpdate(value = false)
public class Identity extends Component {
@Id public long id;
public String tag;
public String typeID;
@Version public long version;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chunk_id") // I suppose the Chunk entity has id
public Chunk chunk;
}
@Entity
@Table(name = "chunk", uniqueConstraints = {@UniqueConstraint(columnNames={"x", "y"})}, indexes = {@Index(columnList = "x,y")})
@Access(value = AccessType.FIELD)
@SelectBeforeUpdate(false)
public class Chunk extends HibernateComponent {
public int x;
public int y;
public Date createdOn;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "chunk")
@Fetch(FetchMode.JOIN)
@BatchSize(size = 50)
public Set<Identity> inChunk = new LinkedHashSet<>();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.