簡體   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