hibernate多对多关系维护

hibernate多对多关系维护主要是级联新增与级联删除,这里以书籍(Book)和书籍类别(Category)为例来讲解Hibernate关联映射中的多对多关联关系的维护,相关数据库设计、实体类、配置文件见:https://blog.csdn.net/weixin_42687829/article/details/83385610

两个配置文件的inverse属性共有四种组合方式:1、Book.hbm.xml:true,Category.hbm.xml:false代表的意思是将关系维护的责任交给Category;2、Book.hbm.xml:false,Category.hbm.xml:true代表的意思是将关系维护的责任交给Book;3、两个都为true;4、两个都为false。这里先以第二种配置方式为例:

1、级联新增

测试新增书本:

        /**
	 * 新增书本的方法
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:05:40
	 * @param book
	 * @return
	 */
	public Integer save(Book book) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		Integer bid = (Integer) session.save(book);
		transaction.commit();
		SessionFactoryUtil.closeSession();
		return bid;
	}

        /**
	 * 新增书本:填写书本信息->勾选复选框类别->提交
	 * jdbc的做法:bookDao.add()、categoryDao.add()
	 * hibernate做法:bookDao.add()
	 * 
	 * 配置:
	 *	   book.hbm:false
	 *	   category.hbm:true
	 * 代表的意思是将关系维护的责任交给book
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:32:28
	 */
	@Test
	public void testSaveBook() {
		Book book=new Book();
		book.setBookName("你是最好的自己");
		Category category=new Category();
		category.setCategoryId(3);
		/*
		 * 错误写法:book.getCategorys().add(category);
		 * 异常Caused by: 
		 * 	com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
		 * 		Column 'category_name' cannot be null
		 * 因为hibernate通过管理持久态对象来操作数据库,所以要先查询一下将category变成持久态
		 */
		book.getCategorys().add(this.categoryDao.get(category));
		this.save(book);
	}

结果:书籍表和桥接表都新增成功,没有异常

测试新增书籍类别:

        /**
	 * 新增类别的方法
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:14:04
	 * @param category
	 * @return
	 */
	public Integer save(Category category) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		Integer cid = (Integer) session.save(category);
		transaction.commit();
		SessionFactoryUtil.closeSession();
		return cid;
	}

        /**
	 * 当配置为:
	 *	   book.hbm:false
	 *	   category.hbm:true时,操作category是不能往桥接表里添加数据的
	 * 因为其代表的意思是将关系维护的责任交给book,所以这种添加方式是不可行的
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:42:37
	 */
	@Test
	public void testSaveCategory() {
		Category category=new Category();
		category.setCategoryName("玄幻");
		Book book=new Book();
		book.setBookId(5);
		category.getBooks().add(this.bookDao.get(book));
		this.categoryDao.save(category);
	}

结果:书籍列表新增成功,但桥接表没有新增,没有报异常

当配置都为true时测试新增书籍:

        /**
	 * 当配置为:
	 *	   book.hbm:true
	 *	   category.hbm:true时会出现中间表无对象维护的情况,即书本能添加进去,但中间表无法添加
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:46:22
	 */
	@Test
	public void testSaveBook2() {
		Book book=new Book();
		book.setBookName("你是最好的自己2");
		Category category=new Category();
		category.setCategoryId(3);
		book.getCategorys().add(this.categoryDao.get(category));
		this.save(book);
	}

结果:书本能添加进去,但中间表无法添加

当配置都为false时测试新增书籍:

         /**
	 * 当配置为:
	 *	   book.hbm:false
	 *	   category.hbm:false
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:46:22
	 */
	@Test
	public void testSaveBook3() {
		Book book=new Book();
		book.setBookName("你是最好的自己2");
		Category category=new Category();
		category.setCategoryId(3);
		book.getCategorys().add(this.categoryDao.get(category));
		this.save(book);
	}

结果:书本能添加进去,中间表也能添加进去,但若再新增书本类别且是同一组关系,依然能新增进去,造成数据重复的现象

 2、级联删除(以第二种配置方式为例)

删除主控方(Book):

        /**
	 * 删除书本的方法
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:50:19
	 * @param book
	 */
	public void del(Book book) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		session.delete(book);
		transaction.commit();
		SessionFactoryUtil.closeSession();
	}

        /**
	 * 删除主控方book
	 * 结论:一并将从表关联的中间表信息删除
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:52:13
	 */
	@Test
	public void testDelBook() {
		Book book=new Book();
		book.setBookId(5);//删除书本ID为5的
		this.del(book);
	}

结果:一并将从表关联的中间表信息删除

删除被控方(Category):

        /**
	 * 删除类别(被控方)
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:51:05
	 * @param category
	 */
	public void del(Category category) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		session.delete(category);
		transaction.commit();
		SessionFactoryUtil.closeSession();
	}

        /**
	 * 删除被控方category
	 * 结论:删除失败
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:54:52
	 */
	@Test
	public void testDelCategory() {
		Category category=new Category();
		category.setCategoryId(2);
		this.del(category);
	}

以上做法会删除失败且报异常:Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t_hibernate_book_category`, CONSTRAINT `t_hibernate_book_category_ibfk_2` FOREIGN KEY (`cid`) REFERENCES `t_hibernate_category` (`category_id`)),这是因为主外键约束出现的异常。

解决:被控方先通过主控方解除多对多关系,再删除被控方。

        /**
	 * 删除类别(被控方)
	 * 若直接删除会失败,因为被控方被中间表所引用
	 * 解决:1、解除关联关系(先删除中间表的引用数据)
	 * 		2、再去删除主表信息
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:51:05
	 * @param category
	 */
	public void del(Category category) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		Category c = session.get(Category.class, category.getCategoryId());
		//c里面保存着与某一些书籍相关联的关系
		for (Book b : c.getBooks()) {
			/*
			 * 注意关联关系是交于book,所以解除关系应b.getCategorys().remove(c),
			 * 而不是c.getBooks().remove(b)
			 */
			b.getCategorys().remove(c);
		}
		session.delete(c);
		transaction.commit();
		SessionFactoryUtil.closeSession();
	}

        /**
	 * 删除被控方category
	 * @author LJ
	 * @Date 2018年10月27日
	 * @Time 上午10:54:52
	 */
	@Test
	public void testDelCategory() {
		Category category=new Category();
		category.setCategoryId(2);
		this.del(category);
	}

注意:关联关系交于哪一方就由哪一方来解除关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值