Following example shows how version attribute is affected while updating an entity relationships.
Example
The Entity
@Entity
public class Employee {
@Id
@GeneratedValue
private long id;
@Version
private long version;
private String name;
private String department;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Phone> phones;
.............
}
@Entity
public class Phone {
@Id
@GeneratedValue
private int id;
@Version
private long version;
private String number;
private String type;
.............
}
Updating Relationship
We are going to modify existing phone number of a particular employee.
public class UpdatingRelationExample {
private static EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("example-unit");
public static void main(String[] args) {
try {
persistEmployee();
employeePhoneUpdate1();
employeePhoneUpdate2();
loadEmployee();
} finally {
entityManagerFactory.close();
}
}
private static void employeePhoneUpdate1() {
System.out.println("Update 1 starts, changing employee existing phone number");
EntityManager em = entityManagerFactory.createEntityManager();
Employee employee = em.find(Employee.class, 1L);
em.getTransaction().begin();
employee.getPhones().get(0).setNumber("111-222-3333");
em.getTransaction().commit();
em.close();
System.out.println("Employee updated 1: " + employee);
}
private static void employeePhoneUpdate2() {
System.out.println("Update 2 starts, changing employee existing phone number again");
EntityManager em = entityManagerFactory.createEntityManager();
Employee employee = em.find(Employee.class, 1L);
em.getTransaction().begin();
employee.getPhones().get(0).setNumber("222-333-3333");
em.getTransaction().commit();
em.close();
System.out.println("Employee updated 2: " + employee);
}
private static void loadEmployee() {
EntityManager em = entityManagerFactory.createEntityManager();
Employee employee = em.find(Employee.class, 1L);
System.out.println("Employee loaded: " + employee);
}
public static void persistEmployee() {
Employee employee = new Employee("Joe",
"IT", Phone.cell("111-111-1111"));
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(employee);
em.getTransaction().commit();
em.close();
System.out.println("Employee persisted: " + employee);
}
} Employee persisted: Employee{id=1, version=0, name='Joe', department='IT', phones=[Phone{id=2, version=0, number='111-111-1111', type='cell'}]} Update 1 starts, changing employee existing phone number Employee updated 1: Employee{id=1, version=0, name='Joe', department='IT', phones=[Phone{id=2, version=1, number='111-222-3333', type='cell'}]} Update 2 starts, changing employee existing phone number again Employee updated 2: Employee{id=1, version=0, name='Joe', department='IT', phones=[Phone{id=2, version=2, number='222-333-3333', type='cell'}]} Employee loaded: Employee{id=1, version=0, name='Joe', department='IT', phones=[Phone{id=2, version=2, number='222-333-3333', type='cell'}]}
As seen above, modifying existing phone numbers for an employee does not change the Employee's version number but it changes for the Phone entity which is being modified. That also means, in this scenario OptimisticLockException might be thrown on Phone's version conflict.
Adding new phones or deleting old phones, however, will affect the Employee's version instead of the existing Phone's versions:
public class UpdatingRelationExample2 {
private static EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("example-unit");
public static void main(String[] args) {
try {
persistEmployee();
addNewPhone1();
addNewPhone2();
loadEmployee();
} finally {
entityManagerFactory.close();
}
}
private static void addNewPhone1() {
System.out.println("Update 1 starts, adding new phone number for the employee");
EntityManager em = entityManagerFactory.createEntityManager();
Employee employee = em.find(Employee.class, 1L);
em.getTransaction().begin();
employee.getPhones().add(Phone.work("222-222-2222"));
em.getTransaction().commit();
em.close();
System.out.println("Employee updated 1: " + employee);
}
private static void addNewPhone2() {
System.out.println("Update 2 starts, adding another new phone number for the employee");
EntityManager em = entityManagerFactory.createEntityManager();
Employee employee = em.find(Employee.class, 1L);
em.getTransaction().begin();
employee.getPhones().add(Phone.home("333-333-3333"));
em.getTransaction().commit();
em.close();
System.out.println("Employee updated 2: " + employee);
}
.............
} Employee persisted: Employee{id=1, version=0, name='Joe', department='IT', phones=[Phone{id=2, version=0, number='111-111-1111', type='cell'}]} Update 1 starts, adding new phone number for the employee Employee updated 1: Employee{id=1, version=1, name='Joe', department='IT', phones=[Phone{id=2, version=0, number='111-111-1111', type='cell'}, Phone{id=3, version=0, number='222-222-2222', type='work'}]} Update 2 starts, adding another new phone number for the employee Employee updated 2: Employee{id=1, version=2, name='Joe', department='IT', phones=[Phone{id=2, version=0, number='111-111-1111', type='cell'}, Phone{id=3, version=0, number='222-222-2222', type='work'}, Phone{id=4, version=0, number='333-333-3333', type='home'}]} Employee loaded: Employee{id=1, version=2, name='Joe', department='IT', phones=[Phone{id=2, version=0, number='111-111-1111', type='cell'}, Phone{id=3, version=0, number='222-222-2222', type='work'}, Phone{id=4, version=0, number='333-333-3333', type='home'}]}
Example ProjectDependencies and Technologies Used: - h2 1.4.196: H2 Database Engine.
- hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
Implements javax.persistence:javax.persistence-api version 2.1 - JDK 1.8
- Maven 3.3.9
|
|