0

Lets say there is a persistable class with some properties and one collection(oneToMany mapping). Lets assume initially there is only one record with an id and with no collection saved in it initially.

Lets say that there's a Thread T1 which loads the same record, and while this thread is running, there is another thread T2 which Loads and updates no other property except adds one collection object to the same record(there is only one to avoid confusion). Now T1 tries to save the entity by modifying the feilds of the record, and in a test case i found that it is able to do it without any StaleStateException.

I wanted to find out a way in long conversations, Extended persistence context without adding a version in your database, can you force hibernate to check the associations also? I am almost sure that there is no solution like this! but I am hopeful...Please suggest any solutions!

Placing some rude code...this allowed me to persist.

  Person per = new Person();
    per.setLdt(LocalDateTime.MIN);
    per.setName("Raju");
    per.setPassportNo("Passport123");

    Relations re = new Relations("Raju", "Kavitha", "mother");
    List<Relations> Rlist = new ArrayList<Relations>();
    Rlist.add(re);
    per.setRels(Rlist);

    Belongings b = new Belongings("Bag", 600, LocalDateTime.MIN);
    List<Belongings> blist = new ArrayList<Belongings>();
    blist.add(b);
    per.setBels(blist);

    Session ss = sessFactory.openSession();
    Transaction tx = ss.beginTransaction();

    ss.save(per);
    tx.commit();
    ss.close();
    Thread t1;
    t1 = new Thread(new Runnable() {
        public void run() {
            System.out.println("Thread T1 Started");
            Session session = sessFactory.openSession();
            Transaction tx = session.beginTransaction();

            Person p = (Person) session.load(Person.class, "Raju");
//                p.setPassportNo("passT1");
                p.getAddresses();p.getRels();
                System.out.println("Thread T1 Paused");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Running.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.out.println("Thread T1 Playing again");

            session.save(p);
            tx.commit();
            session.close();

            System.out.println("Thread T1 Ended");
        }
    });

    Thread t2 = new Thread(new Runnable() {

        public void run() {
            System.out.println("Thread T2 Started");
            Session session = sessFactory.openSession();
            Transaction tx = session.beginTransaction();
            Person p = (Person) session.load(Person.class, "Raju");
            p.getPassportNo();
            p.getRels();p.getBels();
            Address a = new Address("123", "Lothkunta", "RangaReddy");
            List<Address> listA = new ArrayList<Address>();
            listA.add(a);
            p.setAddresses(listA);
            p.setPassportNo("passT2");
            session.save(p);
            tx.commit();
            session.close();
            System.out.println("Thread T2 Ended");
        }
    });
    System.out.println("Starting Threads***********************");
    System.out.println("Starting Threads***********************");
    System.out.println("Starting Threads***********************");

    t1.start();
    t2.start();
    try {
        t1.join();
    } catch (InterruptedException ex) {
        Logger.getLogger(Running.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
        t2.join();
    } catch (InterruptedException ex) {
        Logger.getLogger(Running.class.getName()).log(Level.SEVERE, null, ex);
    }
    System.exit(0);
}

Class person is below here/...

@Entity
@Table(name = "PERSON")
@org.hibernate.annotations.OptimisticLocking(type = OptimisticLockType.ALL)
@DynamicUpdate(true)
public class Person implements Serializable {

@Id

String name;
String passportNo;

LocalDateTime ldt;

@OneToMany(cascade = CascadeType.ALL)
@Basic(fetch = FetchType.LAZY)
@OptimisticLock(excluded = false)
@ElementCollection
List<Address> addresses;

@Basic(fetch = FetchType.LAZY)
@OneToMany(cascade = CascadeType.ALL)
@OptimisticLock(excluded = false)
@ElementCollection
List<Belongings> bels;

@Basic(fetch = FetchType.LAZY)
@OneToMany(cascade = CascadeType.ALL)
@OptimisticLock(excluded = false)
@ElementCollection
List<Relations> rels;

public String getPassportNo() {
    return passportNo;
}

public List<Address> getAddresses() {
    return addresses;
}

public void setAddresses(List<Address> addresses) {
    this.addresses = addresses;
}

public List<Belongings> getBels() {
    return bels;
}

public void setBels(List<Belongings> bels) {
    this.bels = bels;
}

public List<Relations> getRels() {
    return rels;
}

public void setRels(List<Relations> rels) {
    this.rels = rels;
}

public void setPassportNo(String passportNo) {
    this.passportNo = passportNo;
}

public LocalDateTime getLdt() {
    return ldt;
}

public void setLdt(LocalDateTime ldt) {
    this.ldt = ldt;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

Thanks!

Abhijeet
  • 689
  • 2
  • 10
  • 19

1 Answers1

0

No, there is no way to do it without the version field. And even with the version field, you will have to force the version update on the parent if you want to protect collection modifications; see LockModeType.OPTIMISTIC_FORCE_INCREMENT.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110