假设有一个具有一些属性和一个集合(oneToMany映射)的可持久化类。让我们假设最初只有一个带有id的记录,并且最初没有保存集合。
让我们说有一个线程T1加载相同的记录,当这个线程运行时,还有另一个线程T2加载并更新没有其他属性,除了将一个集合对象添加到同一记录(只有一个到避免混淆)。 现在T1尝试通过修改记录的数量来保存实体,并且在测试用例中我发现它能够在没有任何StaleStateException的情况下执行它。
我想在长对话中找到一种方法,扩展持久化上下文而不在数据库中添加版本,你是否可以强制hibernate检查关联?我几乎可以肯定没有这样的解决方案!但我很有希望......请提出任何解决方案!
放置一些粗鲁的代码......这让我坚持下去。
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 :(得分:0)
不,没有版本字段就没有办法做到这一点。即使使用版本字段,如果要保护集合修改,也必须强制更新父版本;见LockModeType.OPTIMISTIC_FORCE_INCREMENT。