[英]Hibernate generates unnecessary queries
我正在使用Hibernate 3.3.1。
我在db中有一张表(2个字段: id
, name
)。 使用Hibernate我已经为该表创建了一个类。
@Entity
@Table(name = "table1")
public class QTable1 implements Serializable {
public QTable1() {
}
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO) //<- modification: to comment this line
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
进行更改后,我想使用session.saveorUpdate
保存它们,并保存所有从db加载的行。 即使它们没有改变:
update table1 set name='a' where id=1
update table1 set name='b' where id=2
update table1 set name='cc' where id=3 // only this row changed
代码,修改实体:
final QTable1 item = (QTable1) listTable1.getSelectedValue();
if (item != null) {
item.setName(table1Name.getText());
}
交易代码:
final Session session = Commons.getSessionFactory().openSession();
session.beginTransaction();
for (Object o : pool.getTable1List().toArray()) {
final QTable1 item = (QTable1) o;
session.saveOrUpdate(item);
}
session.getTransaction().commit();
为什么要保存所有数据?
如果我更改id的实现(删除@GeneratedValue(strategy=GenerationType.AUTO)
):
@Id
@Column(name = "id")
private Long id;
它仅保存受影响的行。 这就是我的期望。 但是如果没有@GeneratedValue
如果我尝试向表中添加新行,则必须手动指定id
,这不好。
在调试时,我看到使用@GeneratedValue
我在entitySnapshotsByKey
会话PersistanceContext
中没有实体,因此它认为我的实体是新实体,必须刷新到db。
如何解决这个问题?
更新:
如果我们使用@GeneratedValue
批注,则session.saveOrUpdate(item)
仅生成update
或insert
查询。 但是,如果我们不使用@GeneratedValue
注释session.saveOrUpdate(item)
生成1) select
table1查询2)比较对象是否相等3)决定是否需要生成update
或insert
查询。
现在我不明白为什么@GeneratedValue
阻止查询值。 仍然我不明白,如果休眠状态在内存中有选定行的副本( entitySnapshotsByKey
),为什么会进行select
查询。
但是我发现了一种适合我的溶剂化方法。 我所需要的只是将session.saveOrUpdate(item)
替换为session.merge(item)
。 它会隔离select
查询,并比较值(是否使用@GeneratedValue
)。 唯一的缺点-是潜在的大量查询。
谢谢大家。 如果您能帮助我防止生成select
查询,将非常高兴。
在较低版本的第三版中的某个地方,休眠更改了行为-如果它认为已更改,则不再需要显式保存已加载实体(当然,没有适当的文档-这已经使我的屁股大伤了很多)。 您可能还会使用未保存的值设置。
如果您想防止保存持久化实体,则必须将它们与会话分离。
这是预期的行为并已记录。 saveOrUpdate
接受一个分离的(带有ID)或临时实体(不带ID),然后对其进行更新(如果它是分离的)或保存它(如果它是瞬时的)。
saveOrUpdate
不知道某些字段是否已更改。 它只需要一个实体并将其写入数据库。
您可以使用merge
,它从数据库中获取具有给定ID的实体,然后将所有字段从分离的实体中复制到附加的实体中(然后,如果发生更改,则在刷新时将该实体写入数据库)。 但这需要一个选择来获取数据库,并能够将新状态与旧状态进行比较。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.