1.Cascade是级联动作,在many_to_one中如果使用cascade可以级联操作关联对象,如下代码可以级联保存Category对象。
在Book的映射文件设置
在保存book时,如果book所对应的category没有保存,那么先保存category再保存book,完成级联保存数据的动作。
Cascade默认值是none,不进行级联动作;
Cascade可以为delete, 在many_to_one中cascade不会设置为delete,因为可能会造成异常,除非是基于外键的一对一。
Cascade还可以为all, all表示可以进行所有的级联动作。
在one_to_many中使用cascade:
在保存一端数据时,如果发现关系对象多端数据没有保存,那么会级联保存book; 但是在一端使用级联保存,会多出n条更新语句,所以效率比较低。(即如果多的一端未保存,在一的一端使用级联保存时,会多出n条更新语句,效率较低;所以这种情况下,推荐在多端使用级联,而不推荐在一端使用)
如果在一端cascade="delete",那么在删除一端数据时,会级联将多端的所有数据删除。(慎用)
注意:cascade要起作用,那么一定要设置关联对象。如果关联对象不存在,那么cascade不会有作用。建议少用cascade,甚至不用。
2. inverse:反转, 在hibernate中用于在一的一端来控制关系(外键)由谁来管理(crud)。
表示关系(外键)由Book一端来维护(即多的一端)。也就是说要为book对象设置好book对象对应的Category属性,外键才会被维护(保存)。
@Test public void testInit(){ Session session = null; Transaction tx = null; try { session = HibernateUtil.getSession(); tx = session.beginTransaction(); Category c1 = new Category("计算机类"); Category c2 = new Category("文学"); Category c3 = new Category("历史"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); Book b1 = new Book("java","sun",30,df.parse("1995-05-23")); b1.setCategory(c1); Book b2 = new Book("struts","apache",40,df.parse("2006-09-12")); b2.setCategory(c1); Book b3 = new Book("明朝那些事儿","当年明月",70,df.parse("2008-05-23")); b3.setCategory(c3); Book b4 = new Book("水浒传","老撕",20,df.parse("1985-05-23")); b4.setCategory(c2); c1.getBooks().add(b1); c1.getBooks().add(b2); c2.getBooks().add(b4); c3.getBooks().add(b3); session.save(c1); session.save(c2); session.save(c3); tx.commit(); } catch (Exception e) { if(tx!=null) tx.rollback(); }finally { HibernateUtil.close(); } }
如果 inverse=false ,说明一的一端也可以维护关系,也就是说可以通过在一的一端添加多的一端数据,来保存外键关系。
@Test public void testInit(){ Session session = null; Transaction tx = null; try { session = HibernateUtil.getSession(); tx = session.beginTransaction(); Category c1 = new Category("计算机类"); Category c2 = new Category("文学"); Category c3 = new Category("历史"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); Book b1 = new Book("java","sun",30,df.parse("1995-05-23")); Book b2 = new Book("struts","apache",40,df.parse("2006-09-12")); Book b3 = new Book("明朝那些事儿","当年明月",70,df.parse("2008-05-23")); Book b4 = new Book("水浒传","老撕",20,df.parse("1985-05-23")); c1.getBooks().add(b1); c1.getBooks().add(b2); c2.getBooks().add(b4); c3.getBooks().add(b3); session.save(c1); session.save(c2); session.save(c3); tx.commit(); } catch (Exception e) { if(tx!=null) tx.rollback(); }finally { HibernateUtil.close(); } }
但是要通过更新语句来完成。所以一般情况下,inverse=true.
在多的一端没有inverse, 因为多的一端默认可以维护关系。
注意:级联和 inverse 都是通过关联对象来完成的,如果没有设置关联对象,这两者均不起作用。在两者都设置的情况,要注意区分谁管理级联,谁管理关系。有可能一个关联对象既管理关系又管理级联。