英文:
Prevent hibernate from selecting children when updating its parent?
问题
问题
当我更新父类时,Hibernate 在触发更新之前会选择所有子类。只有当我们添加尚未在数据库中持久的新子项时,才会出现这种情况。Hibernate 逐个选择这些子项,非常... 非常慢。
已经启用并且在正常插入、更新和删除操作中有效的批处理。我为子类提供了一个版本,但是 Hibernate 无法解释它。
select * from identity...
select * from identity...
select * from identity...
select * from identity...
insert .... into identity...
update chunk set ....
问题
是否有办法让 Hibernate 批处理这些查询,或者实现其他机制,使 Hibernate 在首先从数据库中选择新添加的子项之前,仅仅检查它们是否是新的?
基本上,我想摆脱这些“逐个”查询。对于任何可以提供的帮助,我都会感激不尽。
我的类
当我更新包含多个尚未在数据库中的标识(inChunk)的块时... 它尝试确定它们是否在数据库中,从而为每个子项生成一个查询,以过滤需要插入的那些子项... 我如何防止这些多余的查询?我仍然希望保留级联行为。
@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<>();
}
英文:
The Problem
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 ....
Question
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.
My Classes
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<>();
}
答案1
得分: 1
单向一对多关联 - 不是一个好的实践。我建议在Identity
类中定义多对一关联,然后在inChunk
字段的@OneToMany
注解上添加mappedBy
属性,然后在添加新子项之前获取Chunk.inChunk
关联。
@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") // 我假设Chunk实体有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<>();
}
英文:
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<>();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论