乐观锁定模式和session.get()与session.createQuery()



我有一个简单的实体,它有一个属性和乐观锁模式的版本。

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {
@Id
private Integer id;
@Version
@Column(name = "VERSION")
private Long version;
@Column(name = "NAME")
private String name;
}

我想使用处于分离状态的实例。

步骤1。我打开一个会话以某种方式加载一个实例,关闭该会话。

Session session = ... ;
Person person = session.get(Person.class, 1);
session.close();

步骤2。我更改了处于分离状态的人的属性值。

person.setName("Bob");

步骤3。我打开新的会话,合并实例并要求会话用.get方法为我返回实例

Session session = ... ;
person = session.merge(person);
// something happen there
// and then we decide to get our instance from session
person = session.get(Person.class, 1); 
System.out.println(person.getVersion()); // result is 0

步骤4。我做了与步骤3中相同的事情,但使用了查询。

Session session = ... ;
person = session.merge(person);
// something happen there
// and then we decide to get our instance from session
Query<Person> query = session.createQuery("from Person p where p.id = :id", Person.class);
query.setParameter("id", 1L);
person = query.list().iterator().next();
System.out.println(person.getVersion()); // result is 1

那么,这里有什么区别?这两种情况都访问了数据库,但只有第二种情况进行了版本更新(这种行为对我来说似乎是错误的,因为如果我重复步骤4两次,我将得到DbConcurrentModificationException异常(。我在哪里错过了什么?我在哪里可以读到这件事?为什么版本更新不及时?

休眠5.4.12.最终

谢谢你的帮助!

您不考虑冲洗。

Flushing是将持久性上下文的状态与底层数据库同步的过程。

6.1自动冲洗

默认情况下,Hibernate使用AUTO刷新模式,在以下情况下触发刷新:

  • 提交交易之前

  • 在执行与排队实体动作重叠的JPQL/HQL查询之前

  • 在执行任何没有注册同步的本机SQL查询之前

因此,当您执行查询时

Query<Person> query = session.createQuery("from Person p where p.id = :id", Person.class);

Hibernate隐式地将持久性上下文的状态与数据库同步。

但是,当您调用merge方法时,您应该自己执行。

Session session = sessionFactory.openSession();
Person person = session.get(Person.class, 1L);
session.close();
person.setName("Bob");
Session session2 = sessionFactory.openSession();
Transaction transaction2 = session2.beginTransaction();
person = (Person) session2.merge(person);
session2.flush();
System.out.println(person.getVersion()); // here version will be updated
transaction2.commit();
session2.close();

最新更新