package cyrille.hibernate; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Version; import junit.framework.TestCase; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.time.DateFormatUtils; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; public class MergeTest extends TestCase { @Entity public static class Customer { @Temporal(value = TemporalType.DATE) protected Date birthDate; @Id @GeneratedValue protected Long id; @Basic protected String lastName; @Version protected int version; @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Customer other = (Customer) obj; return new EqualsBuilder().append(this.id, other.id).isEquals(); } public Date getBirthDate() { return birthDate; } public Long getId() { return id; } public String getLastName() { return lastName; } public int getVersion() { return version; } @Override public int hashCode() { return new HashCodeBuilder().append(this.id).toHashCode(); } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public void setId(Long id) { System.out.println("use setId on " + this); this.id = id; } public void setLastName(String lastName) { this.lastName = lastName; } public void setVersion(int version) { this.version = version; } @Override public String toString() { return new ToStringBuilder(this).append("id", this.id).append("version", this.version).append("lastName", this.lastName) .append("birthDate", this.birthDate).toString(); } } protected SessionFactory sessionFactory; @Override protected void setUp() throws Exception { super.setUp(); AnnotationConfiguration configuration = new HsqldbAnnotationConfiguration(); configuration.addAnnotatedClass(Customer.class); configuration.configure(); this.sessionFactory = configuration.buildSessionFactory(); } public void testMerge() throws Exception { Long customerId; { // CREATE sessionFactory.getCurrentSession().beginTransaction(); Customer customer = new Customer(); customer.setLastName("Le Clerc"); sessionFactory.getCurrentSession().save(customer); sessionFactory.getCurrentSession().getTransaction().commit(); System.out.println("created customer: " + customer); customerId = customer.getId(); sessionFactory.getCurrentSession().close(); } { // RELOAD AND UPDATE sessionFactory.getCurrentSession().beginTransaction(); Customer customer = (Customer) sessionFactory.getCurrentSession().get(Customer.class, customerId); customer.setBirthDate(new GregorianCalendar(1976, 0, 5).getTime()); sessionFactory.getCurrentSession().update(customer); sessionFactory.getCurrentSession().getTransaction().commit(); System.out.println("updated customer: " + customer); sessionFactory.getCurrentSession().close(); } { // SIMULATE WEB UPDATE String id, version, lastName, birthDate; { // GENERATE PAGE sessionFactory.getCurrentSession().beginTransaction(); Customer customer = (Customer) sessionFactory.getCurrentSession().get(Customer.class, customerId); id = customer.getId().toString(); version = String.valueOf(customer.getVersion()); lastName = customer.getLastName(); birthDate = DateFormatUtils.format(customer.getBirthDate(), "yyyy/MM/dd"); sessionFactory.getCurrentSession().getTransaction().commit(); sessionFactory.getCurrentSession().close(); } concurrentModification(customerId); { // UPDATE DATA IN THE WEB FORM System.out.println("web modificatino of version " + version); birthDate = "1975/01/01"; } { // UPDATE OBJECT WITH FORM DATA sessionFactory.getCurrentSession().beginTransaction(); // business check Customer customerforCheck = (Customer) sessionFactory.getCurrentSession().get(Customer.class, customerId); customerforCheck.getBirthDate(); // hibernate update Customer customer = new Customer(); customer.setId(new Long(id)); customer.setVersion(Integer.parseInt(version)); customer.setLastName(lastName); customer.setBirthDate(new SimpleDateFormat("yyyy/MM/dd").parse(birthDate)); /* * merge = - load from session - override each field's value - recurse ? */ Customer mergedCustomer = (Customer) sessionFactory.getCurrentSession().merge(customer); assertSame(customerforCheck, mergedCustomer); sessionFactory.getCurrentSession().getTransaction().commit(); sessionFactory.getCurrentSession().close(); System.out.println("updated reconnected customer: " + customer); } } } public void concurrentModification(Long customerId) { sessionFactory.getCurrentSession().beginTransaction(); Customer customer = (Customer) sessionFactory.getCurrentSession().get(Customer.class, customerId); System.out.println("concurrent modification of version " + customer.getVersion()); customer.setBirthDate(new GregorianCalendar(1989, 03, 06).getTime()); sessionFactory.getCurrentSession().save(customer); sessionFactory.getCurrentSession().getTransaction().commit(); System.out.println("concurrently modified customer " + customer); sessionFactory.getCurrentSession().close(); } }