org.hibernate.TransientObjectException

使用JPA注解@ManyToMany做一个多对多的用例。

为了避免在删除主表数据时同时级联删除从表数据,JPA官方文档建议在主表的从表字段使用级联注解:CascadeType.PERSIST,CascadeType.MERGE,进行配置。

主表代码:

1   private Set<Hobby> hobby;
2     
3    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER)
4    @JoinTable(name = "CAT_HOBBY", 
5        joinColumns = { @JoinColumn(name = "CAT_ID") },
6        inverseJoinColumns = { @JoinColumn(name = "HOBBY_ID") })
7    public Set<Hobby> getHobby() {
8        return hobby;
9    }

从表代码:

1   private Set<Cat> cat;
2     
3    @ManyToMany(mappedBy = "hobby",fetch=FetchType.LAZY)
4    public Set<Cat> getCat() {
5        return cat;
6    }
7    public void setCat(Set<Cat> cat) {
8        this.cat = cat;
9    }

Dao层代码:

 1    public static Object save(Object obj){
 2         Session session = HibernateUtil.getSession();
 3         Transaction tx = null;
 4         try {
 5             tx = session.beginTransaction();
 6             session.save(obj);
 7             tx.commit();
 8         } catch (RuntimeException e) {
 9             if (tx != null) {
10                 tx.rollback();
11             }
12             throw e;
13         } finally {
14             session.close();
15         }
16         return obj;
17     }

main代码:

 1      Cat cat1 = new Cat();
 2         Cat cat2 = new Cat();
 3         cat1.setCat_name("b12_ManyToMany5");
 4         cat2.setCat_name("b12_ManyToMany6");
 5 
 6         Set<Hobby> hobbies = new HashSet<Hobby>();
 7         Hobby hobby1 = new Hobby();
 8         hobby1.setName("球1");
 9         hobbies.add(hobby1);
10         
11         Hobby hobby2 = new Hobby();
12         hobby2.setName("球2");
13         hobbies.add(hobby2);
14         
15         cat1.setHobby(hobbies);
16         cat2.setHobby(hobbies);
17         
18         HibernateUtil.save(cat1);
19         HibernateUtil.save(cat2);
20         System.out.println(cat1.getId());
21         System.out.println(cat2.getId());

运行main方法,第18行报如下异常,这应该是一个Hibernate实现JPA接口的一个bug。

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: b12_ManyToMany_JoinTable.Hobby

策略一,使用CascadeType.ALL注解,可以保存,但在删除操作时,产生ERROR: ORA-02292: 违反完整约束条件 (WXUATUSER.FK_ODDM1C9RTQFPO2HI2BCR4OUQX) - 已找到子记录。不可取。

策略二,改用persist方法保存,报异常:detached entity passed to persist。不可取。

1    tx = session.beginTransaction();
2    session.persist(obj);
3    tx.commit();

策略三,使用Hibernate的注解@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE}),增删改查,达到预期的级联效果,删除主表数据不会级联到从表。可取。

 

posted @ 2015-03-31 13:41  xiluhua  阅读(863)  评论(0编辑  收藏  举报