工作中用hibernate框架,但是呢一直只是粗略知道简单的CRUD,由于不太深入了解hibernate,工作上遇到很多莫名其妙的问题,所以买了一本孙卫琴的书补一下,写下一点琐碎的笔记做为记录,以免以后忘记了,温故而知新嘛。
问题一:
描述:Customer与Order一对多,建立双向关联,只记录关键,其他属性略去不写:
Customer配置文件中:
Order配置文件中:
1.如果Customer配置文件中去掉inverse="true"或设置inverse="false",以下代码报org.hibernate.TransientObjectException:
Session session = sessionFactory.openSession();session.beginTransaction();Customer cus = new Customer("cus1");Order order = new Order();order.setOrderNumber("orderNumber1");//order.setCustomer(cus);//不设置关联Order order2 = new Order();order2.setOrderNumber("orderNumber2");//order2.setCustomer(cus);//不设置关联cus.getOrders().add(order);cus.getOrders().add(order2);session.save(cus);session.getTransaction().commit();session.close();
这是因为hibernate执行完insert以后还会执行更新,所以报上面的错:
Hibernate: insert into CUSTOMERS (NAME, ID) values (?, ?)Hibernate: update ORDERS set CUSTOMER_ID=? where ID=?2.如果设置inverse="true"则不会报错,这是因为session.save(cus);的时候将控制权反转给了对方即Order,不会产生update语句,这样的结果 是只产生一条Hibernate: insert into CUSTOMERS (NAME, ID) values (?, ?)。
3.如果修改Custom配置文件:
再次执行上面的代码,结果将是期望得到的,即产生三条insert插入三条记录,然后再产生两条update更新两个order对象的外键custom_id,总共产生五条sql。
综上其实我们可以总结出来:
如果One这方在set标签中设置inverse=false,custom这方关联多少条order,就会产生多少条update去更新order的外键,即update Order set custom_id = ? where id = ?;它的作用只是产生update语句,一般为了不产生这些多余的sql,一般都设置 为true
问题二:关于inverse与cascade:
custom:
order配置文件和上面相同
执行如下代码:
Session session = sessionFactory.openSession();Customer cus = (Customer) session.load(Customer.class, 1L);session.beginTransaction();session.delete(cus);session.getTransaction().commit();session.close();
上面的代码表达的意思无非就是级联删除,假设数据库有一条ID为1的Customer,两条关联的order,想实现将Customer和其两条关联的order都删除,上面的代码获得如期的效果:
Hibernate: delete from ORDERS where ID=?
Hibernate: delete from ORDERS where ID=?Hibernate: delete from CUSTOMERS where ID=?但是如果将上述inverse="true"去掉:产生sql如下:
Hibernate: update ORDERS set CUSTOMER_ID=null where CUSTOMER_ID=?
Hibernate: delete from ORDERS where ID=?Hibernate: delete from ORDERS where ID=?Hibernate: delete from CUSTOMERS where ID=?它会先去维护两者的关系产生update语句,这时如果你的数据库中外键字段CUSTOMER_ID如果不允许为NULL,则会直接在update时直接产生一个异常,下面SQL不再执行。
由上可以得出:如果cascade与inverse都存在,先inverse再cascade,即先维护关联关系再删除。
上面的结论有个例外,那就是:
如果inverse="true" cascade="delete-orphan",执行下面代码:
Session session = sessionFactory.openSession();Customer cus = (Customer) session.load(Customer.class, 1L);session.beginTransaction();Iteratorit = cus.getOrders().iterator();it.next();it.remove();session.getTransaction().commit();session.close();
Hibernate: delete from ORDERS where ID=?
如果inverse="true" cascade="all",则上面代码不会删除order记录,不会删除记录。