Java JPA@Version字段没有';不能增加
我是JPA和Hibernate新手,乐观锁定有问题。我有一个类,它有一个@Version注释字段。更新此类表示的实体时,版本计数器不会增加。这是我的密码: 班级:Java JPA@Version字段没有';不能增加,java,mysql,hibernate,jpa,transactions,Java,Mysql,Hibernate,Jpa,Transactions,我是JPA和Hibernate新手,乐观锁定有问题。我有一个类,它有一个@Version注释字段。更新此类表示的实体时,版本计数器不会增加。这是我的密码: 班级: @Entity @Table (name = "Studenten") public class Student implements Serializable{ private static final long serialVersionUID = 705252921575133272L; @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.Optimization\u FORCE\u INCREMENT,并收到以下错误消息:
ERROR: HHH000099: an assertion failure occurred (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>
错误:HHH000099:发生断言失败(这可能表示Hibernate中存在错误,但更可能是由于会话使用不安全):org.Hibernate.AssertionFailure:无法强制对非版本化实体增加版本
2014年6月20日上午9:00:52 org.hibernate.AssertionFailure
所以很明显,我有一个未版本化的实体。但是为什么呢?我的类中有@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>
org.hibernate.ejb.HibernatePersistence
有什么问题吗?只有当实体中确实存在一些脏数据(未提交)时,JPA才会更新版本。我假设195948学生的学期价值为“1”。尽管您正在设置与上一个值相等的值,但理想情况下实体状态没有变化。因此,JPA没有更新版本值。如果将“学期”值设置为不同的值(而不是较早的值),则实体的状态会发生更改,并相应地更新“版本”列 谢谢,
JaganentityManager.persist()方法仅用于以前从未持久化过的新实体 因为您正在获取一个实体,所以无论如何都不需要调用persist或merge。脏检查将代表您执行更新 无论如何,提交都会触发刷新,因此您应该可以看到更新
确保您使用的是
javax.persistence.Version
注释,而不是来自另一个包(spring数据或类似的东西)。我可能会发现您的问题的一个要点。
试着替换
private int version
到
因为@Version标记可能无法与基元类型一起使用。谢谢。这可能与主题不完全一致(因为我使用的是SpringData repositories),但当我在寻找问题的答案时,我在这里结束了,因此这可能会帮助下一个人 未返回以下和我的版本字段并进行更新
savedJpa = repository.save(updateJpa);
最后我的解决办法是
savedJpa = repository.saveAndFlush(updateJpa);
谢谢你的回答,但那正是我所做的;)。这个学期的值是2,我将它更新为1。但是为什么要发布SQL更新呢?还有一个甚至懒得检查version字段,这似乎非常危险。事实上,我正在用字段的新值更新学生表。所以它应该检查version字段。我不知道为什么没有。这是我的问题。@Thilo,版本比较是针对内存中的对象与em.find()获取的对象进行的。没有显式查询来检查版本。如果两者不同,JPA会自动抛出一个异常。@Raistlin,您是否在询问为什么在事务提交后数据库中没有进行版本检查或值没有增加?可能您导入了错误的
@version
(从其他库导入)?否,它来自javax.persistence包,其他注释也一样。谢谢你的建议。我删除了对entityManager.persist方法的调用,但问题仍然是一样的。我还检查了版本注释所在的包。它是javax.persistence包:(SQL日志输出版本,因此即使在修改和合并时,您也会看到它为0。好的,但是当我调用“select*from studenten”时,我不应该在输出中看到新的版本值吗?那么,问题仍然是:它为什么不工作;)。注释的包是正确的,persist方法调用被删除,但问题仍然存在,我添加了一个“version”字段,带有@version。它在数据库中更新良好。optlock异常工作正常。问题是在保存后,实体并没有得到更新,DB更新,但实体仍然有旧版本值。我做错了什么?
savedJpa = repository.saveAndFlush(updateJpa);