简体   繁体   English

Hibernate生成不必要的查询

[英]Hibernate generates unnecessary queries

I'm using Hibernate 3.3.1. 我正在使用Hibernate 3.3.1。
I have a table in db (2 fields: id , name ). 我在db中有一张表(2个字段: idname )。 Using Hibernate I have created a class for this table. 使用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;
    }   

}

After making changes I want to save them using session.saveorUpdate and it saves ALL rows, that was loaded form db. 进行更改后,我想使用session.saveorUpdate保存它们,并保存所有从db加载的行。 Even if they wasn't changed: 即使它们没有改变:

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

Code, modifying the entities: 代码,修改实体:

final QTable1 item = (QTable1) listTable1.getSelectedValue();
if (item != null) {
    item.setName(table1Name.getText());
}

Transaction code: 交易代码:

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();

Why it saves all the data? 为什么要保存所有数据?

If I change the implementation of id (delete @GeneratedValue(strategy=GenerationType.AUTO) ): 如果我更改id的实现(删除@GeneratedValue(strategy=GenerationType.AUTO) ):

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

It saves only affected rows. 它仅保存受影响的行。 And that is what I expect. 这就是我的期望。 But without @GeneratedValue if I try to add new row to the table I have to specify id manually, that is not good. 但是如果没有@GeneratedValue如果我尝试向表中添加新行,则必须手动指定id ,这不好。

While debugging I saw that using @GeneratedValue I don't have my entities in session PersistanceContext in entitySnapshotsByKey so it considers that my entities are new and must by flushed to db. 在调试时,我看到使用@GeneratedValue我在entitySnapshotsByKey会话PersistanceContext中没有实体,因此它认为我的实体是新实体,必须刷新到db。

How to solve that problem? 如何解决这个问题?

UPDATE: 更新:

If we use @GeneratedValue annotation session.saveOrUpdate(item) generates only update or insert queries. 如果我们使用@GeneratedValue批注,则session.saveOrUpdate(item)仅生成updateinsert查询。 But if we don't use @GeneratedValue annotation session.saveOrUpdate(item) generates 1) select for table1 queries 2) compares if the objects are equal or not 3) decide if we need to generate update or insert queries. 但是,如果我们使用@GeneratedValue注释session.saveOrUpdate(item)生成1) select table1查询2)比较对象是否相等3)决定是否需要生成updateinsert查询。

Now I can't understand why @GeneratedValue prevents quering the values. 现在我不明白为什么@GeneratedValue阻止查询值。 Still I don't understand why it makes select queries if hibernate have a copy of selected rows in memory ( entitySnapshotsByKey ). 仍然我不明白,如果休眠状态在内存中有选定行的副本( entitySnapshotsByKey ),为什么会进行select查询。

But I found a solvation that fits me just fine. 但是我发现了一种适合我的溶剂化方法。 All I need is just to replace session.saveOrUpdate(item) with session.merge(item) . 我所需要的只是将session.saveOrUpdate(item)替换为session.merge(item) It quaranties that select query will be made and the values will be compared (using @GeneratedValue or not). 它会隔离select查询,并比较值(是否使用@GeneratedValue )。 The only drawback - is the potential large number of queries. 唯一的缺点-是潜在的大量查询。

Thanks to all. 谢谢大家。 Will be glad if you help me to prevent generating select queries. 如果您能帮助我防止生成select查询,将非常高兴。

Somewhere in lower 3-rd version hibernate changed behaviour - it does not anymore require explicit save of loaded entities (of course, without proper documentation - this had biten a big chunk off my ass ) if it deems that they were changed. 在较低版本的第三版中的某个地方,休眠更改了行为-如果它认为已更改,则不再需要显式保存已加载实体(当然,没有适当的文档-这已经使我的屁股大伤了很多)。 You may also play with unsaved value setting. 您可能还会使用未保存的值设置。

In case you like to prevent saving of persisten entities, you have to detach them from session. 如果您想防止保存持久化实体,则必须将它们与会话分离。

This is expected and documented behavior. 这是预期的行为并已记录。 saveOrUpdate takes a detached (with an ID) or transient entity (without an ID), and then updates it (if it's detached) or saves it (if it's transient). saveOrUpdate接受一个分离的(带有ID)或临时实体(不带ID),然后对其进行更新(如果它是分离的)或保存它(如果它是瞬时的)。

saveOrUpdate doesn't know if some field has changed or not. saveOrUpdate不知道某些字段是否已更改。 It just takes an entity and writes it to the database. 它只需要一个实体并将其写入数据库。

You could use merge , which fetches the entity with the given ID from the database, and then copy all the fields from the detached entity to the attached one (and then writes the entity to the database at flush time if something has changed). 您可以使用merge ,它从数据库中获取具有给定ID的实体,然后将所有字段从分离的实体中复制到附加的实体中(然后,如果发生更改,则在刷新时将该实体写入数据库)。 But this would need a select to fetch the database and be able to compare the new state with the old one. 但这需要一个选择来获取数据库,并能够将新状态与旧状态进行比较。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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