2014-06-20 130 views
7

我是JPA和Hibernate的新手,我有一個樂觀鎖定問題。我有一個類,它有一個@Version註釋字段。當我更新由這個類表示的實體時,版本計數器不會增加。這裏是我的代碼: 類:JPA @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> 

這有什麼錯?

+0

也許你導入了錯誤的'@ Version'(來自其他庫)? – Thilo

+0

不,它來自javax.persistence包,因爲所有其他註釋也是如此。 – Raistlin

回答

7

正如我在this article解釋,該entityManager.persist()方法是指只對以前從未堅持新的實體使用。

因爲您正在提取一個實體,所以無需調用persist或merge。 dirty checking將代表您進行更新。

無論如何,提交會觸發刷新,所以你應該看到更新。

請確保您使用javax.persistence.Version註釋,而不是其他包(彈簧數據或類似的東西)。

+0

感謝您的建議。我刪除了entityManager.persist方法的調用,但問題仍然存在。我也檢查了來自版本註釋的包。它是javax.persistence包。 :( – Raistlin

+0

SQL日誌輸出的版本,所以你總是看到它0,即使修改和合並。 –

+0

好吧,但是當我調用「select * from studenten」時,我不應該看到輸出中的新版本值? – Raistlin

1

JPA僅在實體中存在某些髒數據(未提交)時才更新版本。我假設學生195948的學期價值爲「1」。儘管您正在設置與之前的值相等的值,但理想情況下,實體狀態沒有變化。因此,JPA沒有更新版本值。如果您將學期值設置爲不同的值(不是較早的值),則實體狀態會發生變化,並相應地更新版本列。

感謝, 賈根

+0

感謝您的回答,但那正是我所做的;)。學期的價值是2,我將它更新爲1. – Raistlin

+0

但是,爲什麼要發佈SQL UPDATE呢?還有一個甚至不打算檢查版本字段,這看起來非常危險。 – Thilo

+0

那麼,我實際上正在爲學期表更新一個學期表的新值。所以它應該檢查版本字段。我不知道爲什麼它不。這是我的問題。 – Raistlin