繁体   English   中英

Hibernate生成不必要的查询

[英]Hibernate generates unnecessary queries

我正在使用Hibernate 3.3.1。
我在db中有一张表(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保存它们,并保存所有从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)仅生成updateinsert查询。 但是,如果我们使用@GeneratedValue注释session.saveOrUpdate(item)生成1) select table1查询2)比较对象是否相等3)决定是否需要生成updateinsert查询。

现在我不明白为什么@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM