Search code examples
javajpa-2.0eclipselinkjava-ee-6one-to-many

@Version not incremented upon relationship change


According to the JPA 2.0 specification:

The version attribute is updated by the persistence provider runtime when the object is written to the database. All non-relationship fields and properties and all relationships owned by the entity are included in version checks.

This doesn't seem to work in my case. I have two Entities:

@Entity
public class OrderedItem {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @ManyToOne
    private Customer owner;

    @Version
    private int version;

    public OrderedItem(String name) {
        this.name = name;
    }

    // default constructor + bunch of simple accessors and mutators
}

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @OneToMany(mappedBy = "owner")
    private Set<OrderedItem> orderedItems = new HashSet<OrderedItem>();;

    @Version
    private int version;


    public Customer(String name) {
        this.name = name;
    }

    // default constructor + bunch of simple accessors and mutators
}

The "many" side of ManyToOne relationship must be an owning side, so in my case the OrderedItem is the owning side. Following the JPA 2.0 spec, I assume that when I change the Customer object accessed from OrderedItem the version of OrderedItem entity should be incremented. Therefore, I've tried to test it:

Customer john = new Customer("John");
OrderedItem milk = new OrderedItem("Milk");

milk.setOwner(john);
john.getOrderedItems().add(milk);

startTx();

em.persist(john);
em.persist(milk);

stopTx();

startTx();

OrderedItem milkFromPC = em.find(OrderedItem.class, milk.getId());
milkFromPC.getOwner().setName("Michael");

stopTx();

The version numbers are 1 for OrderedItem (so no increment) and 2 for Customer.

Any ideas why?


It just bumped into my head while writing this question - is it possible that the "relationship" word in JPA 2.0 specification means that only if I change the entity -- Customer -- itself (not its state) the version will be incremented? Just like in case of @JoinColumn(updatable=false)?


Solution

  • Yes, as I understand it the version field of OrderedItem will change, if you reassign a different Customer, but not if you change a property of the customer.

    On the other hand, if you add another OrderedItem to the OrderedItem set of the Customer, the version field of the Customer doesn't get updated because it's not the owning side.

    I guess it's useful here to think here in table rows: if any column in a table row changes the version column of that table row gets incremented.

    It's fine if one client updates the name of the OrderedItem and another the name of the Customer - these updates don't conflict.