以Customer表和Contact表为例:
新增:
//一对多增加 @Test public void testPersist() { Customer customer = new Customer(); customer.setName("新客户"); Contact contact = new Contact(); contact.setName("新联系人"); //添加双向关联关系 customer.getContacts().add(contact); contact.setCustomer(customer); EntityManager em = MyJPAUtils.getEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(customer);//我已经在客户上配置了级联属性,所以这里直接保存customer即可 tx.commit(); em.close(); }
更新:
//一对多更新 @Test public void testMerge() { Contact contact = new Contact(); contact.setName("联系人4"); EntityManager em = MyJPAUtils.getEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Customer customer = em.find(Customer.class, Integer.parseInt("1")); customer.getContacts().add(contact);//这一步涉及对象导航查询,所以对应的有个select语句出来 contact.setCustomer(customer);//这一步不写的话,向数据库中插入的记录外键字段值为null //JPA在insert联系人对象的时候直接把customer_id一起插进去了,不会在insert之后出update语句,hibernate则是先insert再update一下 tx.commit(); em.close(); }在这个测试里,如果我不配置级联更新,也不配置mappedBy,那么主表会去维护关联关系,最后看到维护关联关系的
contact.setCustomer(customer);
时,会发现一个瞬时态的对象操作一个持久态对象,报错!如果不配置级联更新,但是配置了mappedBy,这时候主表放弃维护关联关系,并不会去数据库执行什么操作,不会报错,但是更新目的同时也没达到。(这里注意,contact.setCustomer(customer)这么写是不会报错的,但是如果真的需要去数据库里做对应操作那么执行到这里会报错)。
所以正确的解决办法是,同时加上级联更新和mappeBy属性!
级联删除:
//一对多删除 @Test public void testRemove() { EntityManager em = MyJPAUtils.getEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Customer c = em.find(Customer.class, Integer.parseInt("3")); em.remove(c); tx.commit(); em.close(); }从表数据都可以随便删。对于主表,配置了级联删除的时候,连从表数据一块儿删;如果没配置级联删除,当从表没对应数据的时候,能正常删除,若从表有对应数据,删除失败!