我正在使用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
我在PersistanceContext
中的会话entitySnapshotsByKey
中没有我的实体,所以它认为我的实体是新的,必须刷新到db。< / p>
如何解决这个问题?
更新:
如果我们使用@GeneratedValue
注释session.saveOrUpdate(item)
仅生成update
或insert
个查询。
但是,如果我们不使用@GeneratedValue
注释生成session.saveOrUpdate(item)
1){1}}用于table1查询
2)比较对象是否相等
3)决定是否需要生成select
或update
个查询。
现在我无法理解为什么insert
会阻止查询值。
如果hibernate在内存中有所选行的副本(@GeneratedValue
),我仍然不明白它为什么会进行select
查询。
但是我找到了一个适合我的溶剂。
我只需要用entitySnapshotsByKey
替换session.saveOrUpdate(item)
。它会隔离session.merge(item)
查询,并将比较值(使用select
或不使用{})。唯一的缺点是潜在的大量查询。
感谢所有人。如果您帮助我阻止生成@GeneratedValue
查询,我们将很高兴。
答案 0 :(得分:0)
在较低的第3版hibernate中某处改变了行为 - 它不再需要显式保存已加载的实体(当然,没有适当的文档 - 如果它认为它们已被更改,这已经让我的屁股变得很大)。您也可以使用未保存的值设置。
如果您想阻止保存持久性实体,则必须将它们从会话中分离出来。
答案 1 :(得分:0)
这是预期和记录的行为。 saveOrUpdate
采用分离的(带有ID)或瞬态实体(没有ID),然后更新它(如果它已分离)或保存它(如果它是瞬态的)。
saveOrUpdate
不知道某个字段是否已更改。它只需要一个实体并将其写入数据库。
您可以使用merge
从数据库中获取具有给定ID的实体,然后将分离实体中的所有字段复制到附加实体(然后在刷新时将实体写入数据库)如果事情发生了变化)。但是这需要一个select来获取数据库,并能够将新状态与旧状态进行比较。