Java JPA @Version 字段不会增加
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24321280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA @Version field doesn't get incremented
提问by Raistlin
I'm new to JPA and Hibernate and I have a problem with optimistic locking. I have a class wich hase an @Version annotated field. When I update the Entity represented by this class, the version counter does not increase. Here is my code: The class:
我是 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;
}
and here is the main method:
这是主要方法:
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();
}
}
and here is what the console says:
这是控制台所说的:
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=?
Can somebody tell me what's wrong?
有人能告诉我出了什么问题吗?
Edit:ok, I have tried something. I've set the locking to LockModeType.OPTIMISTIC_FORCE_INCREMENT and got this Error-Message:
编辑:好的,我尝试过一些东西。我已将锁定设置为 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>
So it seems clear that I have a non-versioned entity. But why? I have the @Version Annotation in my class.
所以很明显我有一个非版本化的实体。但为什么?我的班级中有 @Version 注释。
Edit:I begin to think that the problem is in the persistence.xml. Here it is:
编辑:我开始认为问题出在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>
Is there anything wrong?
有什么不对的吗?
采纳答案by Vlad Mihalcea
As I explained in this article, The entityManager.persist()
method is meant to be used only for new entities that have never been persisted before.
正如我在本文中所解释的,该entityManager.persist()
方法仅用于以前从未持久化的新实体。
Because you are fetching an entity you don't need to call persist or merge anyway. The dirty checkingwill do the update on your behalf.
因为您正在获取一个实体,所以无论如何都不需要调用 persist 或 merge 。在脏检查将做代表您的更新。
The commit will trigger the flush anyway so you should see the update.
提交无论如何都会触发刷新,因此您应该看到更新。
Make sure you use the javax.persistence.Version
annotation and not from other package (spring data or something similar).
确保您使用javax.persistence.Version
注释而不是来自其他包(弹簧数据或类似的东西)。
回答by HJK
JPA only updates the version only when there really exists some dirty data (uncommitted) present in the entity. I assume Student 195948 already had semester value as "1". Though you are setting the value, which is equal to the previous value, ideally there is no change in the entity state. Hence JPA is not updating the version value. If you set the semester value to different value (not the earlier one), then there is a change in the state of the entity and it updates the version column accordingly.
JPA 仅在实体中确实存在一些脏数据(未提交)时才更新版本。我假设学生 195948 的学期值为“1”。尽管您设置的值等于前一个值,但理想情况下实体状态没有变化。因此 JPA 不会更新版本值。如果您将学期值设置为不同的值(不是较早的值),则实体的状态会发生变化,并相应地更新版本列。
Thanks, Jagan
谢谢,贾根
回答by zhicong Liu
I may find a important point of your issue. Try to replace
我可能会发现你的问题的一个重点。尝试更换
private int version
to
到
private Long version
For the reason that @Version tag may not work with primitive type.Thanks.
由于@Version 标记可能不适用于原始类型。谢谢。
回答by AndrewS
This may not be exactly on topic (as I am using SpringData repositories) but when I was looking for the answer to my problem I ended up here, so this may help the next person.
这可能不完全是主题(因为我使用的是 SpringData 存储库)但是当我在寻找问题的答案时,我最终来到了这里,所以这可能对下一个人有所帮助。
the following and my version field was not being returned updated.
以下和我的版本字段没有被返回更新。
savedJpa = repository.save(updateJpa);
In the end my solution was
最后我的解决方案是
savedJpa = repository.saveAndFlush(updateJpa);