JPA @Version field doesn't get incremented

18,026

Solution 1

The entityManager.persist() method is meant to be used only for new entities that have never been persisted before.

Because you are fetching an entity you don't need to call persist or merge anyway. The dirty checking will do the update on your behalf.

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 another package (spring data or something similar).

Solution 2

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.

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);

Solution 3

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.

Thanks, Jagan

Solution 4

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.

Share:
18,026
Raistlin
Author by

Raistlin

Updated on September 01, 2022

Comments

  • Raistlin
    Raistlin over 1 year

    I'm new to JPA and Hibernate and I have a problem with optimistic locking. I have a class which has 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:

    @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:

    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>
    

    So it seems clear that I have a non-versioned entity. But why? I have the @Version Annotation in my class.

    Edit: I begin to think that the problem is in the persistence.xml. Here it is:

    <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?