2015-07-31 4 views
0

Допустим, что существует устойчивый класс с некоторыми свойствами и одной коллекцией (отображение oneToMany). Предположим, что вначале есть только одна запись с идентификатором и без коллекции, сохраненной в ней изначально.Оптимистичная блокировка в коллекциях без столбца версии в базе данных

Допустим, что есть поток T1, который загружает одну и ту же запись, и пока этот поток запущен, есть еще один поток T2, который загружает и обновляет никакое другое свойство, кроме добавления одного объекта коллекции в одну запись (есть только один чтобы избежать путаницы). Теперь T1 пытается сохранить объект, изменив feilds записи, и в тестовом примере я обнаружил, что он может сделать это без исключения StaleStateException.

Я хотел узнать путь в длинных разговорах, расширенный контекст постоянства без добавления версии в вашу базу данных, вы можете заставить спящий режим также проверить ассоциации? Я почти уверен, что такого решения нет! но я надеюсь ... Пожалуйста, предложите любые решения!

Размещение некоторого грубого кода ... это позволило мне сохраниться.

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); 
} 

Класс люди находятся ниже здесь/...

@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; 
} 
} 

Спасибо!

ответ

0

Нет, нет способа сделать это без поля версии. И даже с полем версии вам придется принудительно обновить версию для родителя, если вы хотите защитить изменения коллекции; см. LockModeType.OPTIMISTIC_FORCE_INCREMENT.