hibernate dirty flag works great for what they call "persistent" objects https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html
but i have a web app, where the hib mang entity Order is also used as the Spring MVC command object. so when my controller marshals the request into an order, it is what hibernate calls a "detached" object. my problem senario can be illustrated with 2 web clients and 4 web requests against a single order.
1 - client 1 opens the order in detail view
2 - client 2 opens the same order and updates attribute 1
3 - client 1 clicks "save" to update any changed fields, but actually has not updated anything
in step 3, client 1 issues session.update(order) (also tried session.merge() and session.saveOrUpdate()) and ends up reverting attribute 1 back to its original value. if it was a "persistent" object, then hibernate would have known that nothing had changed. but because it is a detached object, hibernate actually issues an update for every member of the Order object.
Any ideas on how to get the dirty flag in hibernate detached objects to work like it does in persistent objects?
test first test shows hibernate working with persistent objects, works great, session 1 issues no updates:
try{Class.forName("net.sourceforge.jtds.jdbc.Driver");} catch(Exception e){e.printStackTrace();}
Session session1 = null;
Session session2 = null;
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session1 = sessionFactory.openSession();
session2 = sessionFactory.openSession();
Transaction tx1 = session1.beginTransaction();
Transaction tx2 = session2.beginTransaction();
// order 1 has a null dig user
//session 1 opens order 1
//session 2 opens order 1
//session 2 assigns andrew as dig, save
//session 1 hits save
Query qo1 = session1.createQuery("select o from Order o where o.id = 536258");
Order o1 = (Order)qo1.list().get(0);
Query qo2 = session2.createQuery("select o from Order o where o.id = 536258");
Order o2 = (Order)qo2.list().get(0);
Query qu2 = session2.createQuery("select u from User u where u.id = 7");
User u2 = (User)qu2.list().get(0);
System.out.println("update user session 2 begin");
o2.setDigitizer(u2);
System.out.println("update user session 2 end");
System.out.println("session 2 save begin");
session2.save(o2);
session2.flush();
tx2.commit();
session2.close();
System.out.println("session 2 save end");
System.out.println("session 1 save begin");
session1.save(o1);
session1.flush();
tx1.commit();
session1.close();
System.out.println("session 1 save end");
then here is the same idea but with detached objects and client 1 ends up reverting the update made by client 2:
try{Class.forName("net.sourceforge.jtds.jdbc.Driver");} catch(Exception e){e.printStackTrace();}
Session session1 = null;
Session session2 = null;
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
System.out.println("session 1a start");
session1 = sessionFactory.openSession();
Transaction tx1 = session1.beginTransaction();
Query qo1 = session1.createQuery("select o from Order o where o.id = 536258");
Order o1 = (Order)qo1.list().get(0);
session1.flush();
tx1.commit();
session1.close();
System.out.println("session 1a end");
System.out.println("session 2 start");
session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
Query qo2 = session2.createQuery("select o from Order o where o.id = 536258");
Order o2 = (Order)qo2.list().get(0);
Query qu2 = session2.createQuery("select u from User u where u.id = 7");
User u2 = (User)qu2.list().get(0);
o2.setDigitizer(u2); //here is session 2 update to the order
session2.flush();
tx2.commit();
session2.close();
System.out.println("session 2 end");
//here is the "detached" part, new session, but same domain object instance from above
System.out.println("session 1b start");
session1 = sessionFactory.openSession();
tx1 = session1.beginTransaction();
session1.update(o1); //tried merge -- same result, we revert the session 2 update
session1.flush();
tx1.commit();
session1.close();
System.out.println("session 1b end");