gpt4 book ai didi

java - Hibernate 生成不必要的查询

转载 作者:行者123 更新时间:2023-12-01 05:34:14 31 4
gpt4 key购买 nike

我使用的是 Hibernate 3.3.1。
我在数据库中有一个表(2 个字段:idname)。我使用 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 保存它们,它会保存从数据库加载的所有行。即使它们没有改变:

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 的实现(删除 @GenerateValue(strategy=GenerationType.AUTO)):

@Id
@Column(name = "id")
private Long id;

它仅保存受影响的行。这就是我所期望的。但是如果没有 @GenerateValue,如果我尝试向表中添加新行,我必须手动指定 id,这不好。

在调试时,我发现使用 @GenerateValue 我在 entitySnapshotsByKey 的 session PersistanceContext 中没有我的实体,因此它认为我的实体是新的,必须刷新到数据库。

如何解决这个问题?

更新:

如果我们使用@GenerateValue注释session.saveOrUpdate(item)仅生成updateinsert查询。但是如果我们使用@GenerateValue注释session.saveOrUpdate(item)生成1) select 用于 table1 查询2)比较对象是否相等3) 决定是否需要生成更新插入查询。

现在我不明白为什么 @GeneeratedValue 阻止查询值。我仍然不明白如果 hibernate 在内存中拥有选定行的副本(entitySnapshotsByKey),为什么它会进行 select 查询。

但我找到了一种非常适合我的溶剂。我所需要的只是将 session.saveOrUpdate(item) 替换为 session.merge(item) 。它保证将进行select查询并比较值(使用或不使用@GenerateValue)。唯一的缺点 - 是潜在的大量查询。

谢谢大家。如果您帮助我防止生成 select 查询,我会很高兴。

最佳答案

这是预期的且有记录的行为。 saveOrUpdate 获取分离的实体(带有 ID)或 transient 实体(没有 ID),然后更新它(如果它是分离的)或保存它(如果它是 transient 的)。

saveOrUpdate 不知道某些字段是否已更改。它只需要一个实体并将其写入数据库。

您可以使用merge,它从数据库中获取具有给定 ID 的实体,然后将分离实体中的所有字段复制到附加实体(然后将该实体写入数据库)如果发生变化,则在刷新时)。但这需要一个选择来获取数据库并能够将新状态与旧状态进行比较。

关于java - Hibernate 生成不必要的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8439466/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com