我是JPA和Hibernate的新手,我对乐观锁定有疑问。我有一个拥有@Version注释字段的类。当我更新此类所代表的实体时,版本计数器不会增加。这是我的代码:该类:
@Entity @Table (name = "Studenten") public class Student implements Serializable{ private static final long serialVersionUID = 705252921575133272L; @Version private int version; private int matrnr; private String name; private int semester; public Student (){ } public Student (int matrnr, String name){ this.matrnr = matrnr; this.name = name; } public Student (int matrnr, String name, int semester){ this(matrnr, name); this.semester = semester; }
这是主要方法:
public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("VEDA_Vortrag"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); try{ tx.begin(); Student s = em.find(Student.class, 195948); s.setSemester(1); em.persist(s); tx.commit(); }catch(Exception e){ if(tx != null && tx.isActive()){ tx.rollback(); System.out.println("Error in Transaction. Rollback!"); } } finally{ em.close(); emf.close(); } }
控制台的内容如下:
Hibernate: select student0_.matrnr as matrnr0_0_, student0_.name as name0_0_, student0_.semester as semester0_0_, student0_.version as version0_0_ from Studenten student0_ where student0_.matrnr=? Hibernate: update Studenten set name=?, semester=?, version=? where matrnr=?
有人可以告诉我怎么了吗?
编辑: 好的,我尝试了一些。我已将锁定设置为LockModeType.OPTIMISTIC_FORCE_INCREMENT并收到以下错误消息:
ERROR: HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: cannot force version increment on non-versioned entity Jun 20, 2014 9:00:52 AM org.hibernate.AssertionFailure <init>
因此,很明显我有一个非版本实体。但为什么?我的课堂上有@Version注释。
编辑: 我开始认为问题出在persistence.xml中。这里是:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="VEDA_Vortrag"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/uni"/> <property name="javax.persistence.jdbc.user" value="*******"/> <property name="javax.persistence.jdbc.password" value="******"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> </properties> </persistence-unit>
有什么问题吗?
正如我在本文中所解释的那样,该entityManager.persist()方法只能用于以前从未持久过的新实体。
entityManager.persist()
因为您正在获取实体,所以无论如何都不需要调用持久或合并。在脏检查将做代表您的更新。
无论如何,提交都会触发刷新,因此您应该看到更新。
确保使用javax.persistence.Version注释,而不使用其他包(spring数据或类似数据)。
javax.persistence.Version