[英]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.