我使用的是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
,并将其保存ALL行,已加载表格数据库。即使他们没有改变:
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
我没有在会话PersistanceContext
中的实体entitySnapshotsByKey
,所以它认为我的实体是新的,并且必须刷新到db。
如何解决这个问题?
UPDATE:
如果我们使用@GeneratedValue
注释session.saveOrUpdate(item)
只产生update
或insert
查询。 但是,如果我们不使用@GeneratedValue
注释session.saveOrUpdate(item)
产生 1)select
为table1的查询 2)如果比较的对象是相等的,或者如果我们需要生成update
或insert
查询不 3)决定。
现在我不明白为什么@GeneratedValue
可以防止查询值。 仍然我不明白为什么它使select
查询如果冬眠有内存中选定的行的副本(entitySnapshotsByKey
)。
但我找到了适合我的溶剂。 我需要的仅仅是用session.merge(item)
替换session.saveOrUpdate(item)
。它会对select
查询进行隔离并对值进行比较(使用@GeneratedValue
或不使用)。唯一的缺点是潜在的大量查询。
感谢所有。如果你帮我防止产生select
查询,会很高兴。
您只向我们展示了部分代码。你能否展示QTable1类的其余部分,修改实体的代码以及事务配置? –