hibernate 多对多关系维护(inverse属性值的设置) , 级联新增,删除案例

本文详细介绍了Hibernate中多对多关系的映射,强调了必须定义主控方,并探讨了多对多关系的删除策略,包括主控方直接删除、通过主控方解除关系后再删除以及禁用级联删除。此外,文章重点讲解了inverse属性的四种情况,指出正确的设置方式。同时,提供了级联新增和删除的案例,以及可能遇到的问题和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hibernate的多对多
hibernate可以直接映射多对多关联关系(看作两个一对多)

. 多对多关系注意事项
1 一定要定义一个主控方
2 多对多删除
.1 主控方直接删除
.2 被控方先通过主控方解除多对多关系,再删除被控方
.3 禁用级联删除
3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护

讲解inverse属性;
* 总共四种 (false 是控制方 ,true 是被控制方),其中有两种正确,两种错误
* 1、book:false category:true ✓(代表意思是:将关系维护的责任交给book book为主控方)
* 2、book: true category:false ✓
* 3、book:true category:true ✗
* 4、book:false category:false ✗

案例:
级联新增 inverse属性值的设置
级联删除

(遇到的问题都在案例里)

dao方法 (book差不多) ,

package com.zking.five.dao;

import org.hibernate.Hibernate;
import org.hibernate.Session;

import com.zking.five.entity.Book;
import com.zking.five.entity.Category;
import com.zking.two.util.SessionFactoryUtil;

public class CategoryDao {


/**
 * -----------------------------------six-----------------------------------------------------	
 * @param category
 * @return
 */
	//新增
		public Integer save(Category category) {
			Session session = SessionFactoryUtil.openSession();
			Integer cid = (Integer) session.save(category);
			SessionFactoryUtil.closeSession();
			return cid;
		}
	
		//删除 直接删除主控方
//		public void del(Category category) {
//			Session session = SessionFactoryUtil.openSession();
//				
//			session.delete(category);
//			SessionFactoryUtil.closeSession();
//		}
//		
//		
		
		/** 2.被控方先通过主控方解除多对多关系,再删除被控方
		 * 
		 * 因为被控方被中间表所引用
		 * 1、接触关联关系(主控方解除多对多关系  先删除中间表引用数据)
		 * 2、再删除主控方的相关数据
		 * 
		 * @param category
		 */
		//删除
		public void del(Category category) {
			Session session = SessionFactoryUtil.openSession();
			Category c = session.get(Category.class, category.getCategoryId());
			//c 里面保存着与某一些书籍相关联的关系
			for (Book b : c.getBooks()) {
				//注意:关系交于book维护
//				c.getBooks().remove(b);   这是错误的 主控方是book 要从书里删除c类型  而不是从类型里删除书
				
				b.getCategories().remove(c);
			}
			session.delete(c);
			SessionFactoryUtil.closeSession();
		}
		
		
	
}

测试(book,category都一起)

package com.zking.five.dao;

import org.junit.Test;

import com.zking.five.entity.Book;
import com.zking.five.entity.Category;

public class BookDaoTest {

	private BookDao  bookDao= new BookDao();
	private CategoryDao  categoryDao = new CategoryDao();
	


	/**----------------------------------six---------------------------
	 *- 提交书本信息,勾选复选框类别, 提交
	 * jdbc: bookDao.add,bookCategoryDao.add(中间表)
	 * hibernate :  bookDao.add
	 * 
	 * 讲解inverse属性;
	 * 总共四种  (false 是控制方   ,true 是被控制方),其中有两种正确,两种错误
	 * 1、book:false   category:true		✓(代表意思是:将关系维护的责任交给book  book为主控方)
	 * 2、book: true   category:false		✓
	 * 3、book:true   category:true  		✗
	 * 4、book:false   category:false 		✗
	 */
	
	
	/**错误1:
	 * Caused by: com.mysql.jdbc.exceptions.
	 * jdbc4.MySQLIntegrityConstraintViolationException:
	 *  Column 'category_name' cannot be null
	 *  
	 *  解决方法:这个错误是没有把对象持久态,所以才会出现这个问题把对象通过get方法获取对象持久态就没问题了
	 *  
	 *  */
	
	/**
	 * 注意:
	 * hibernate 通过管理持久态对象来操作数据库
	 */
	@Test
	public void testAdd() {
		/**
		 * 1、book:false   category:true	✓(代表意思是:将维护的责任交给book  book为主控方)
		 */
		Book book = new Book();
		book.setBookName("雨季不再来aaa");
		book.setPrice(30f);	
		//这是错误的示范
//		Category category = new Category();//临时态对象  错误1
//		category.setCategoryId(4);
//		book.getCategories().add(category);
		
		//要通过get获取持久态对象
		Category category = new Category();
		category.setCategoryId(4);
		book.getCategories().add(this.categoryDao.get(category));
		this.bookDao.add(book);
	}
	
	
	
	
	
	/**
	 * 在新增类别的时候不能用第一种维护关系,因为book是主控方,关系的维护是靠book ,
	 * 新增类别 的时候是需要通过category去维护关系(中间表) 所以要用第二种
	 * 2、book: true   category:false	✓
	 * 主控方是  category
	 * 
	 * 总之 新增什么就设置什么是主控方 (inverse="false")
	 * 	
	 * 
	 */
	@Test
	public void testAdd2() {
		Category category = new Category();
		category.setCategoryName("穿越");
		Book book = new Book();
		book.setBookId(4);
		category.getBooks().add(this.bookDao.get(book));
		this.categoryDao.save(category);
	}
	
	
	
	
	/**
	 * 3、book:true   category:true  		✗
	 * 出现错误:中间表无对象维护(新增类别或书籍时    书籍或类别新增了 但是中间表没有数据)
	 */
	@Test
	public void testAdd3() {
		Category category = new Category();
		category.setCategoryName("言情");
		Book book = new Book();
		book.setBookId(5);
		category.getBooks().add(this.bookDao.get(book));
		this.categoryDao.save(category);
	}
	
	
	/**
	 * 4、book:false   category:false 		✗
	 * 相同的数据加入就会在中间表中有重复的数据,
	 * 到时候在查询的时候会重复的数据
	 * 
	 */
	
	
	
	/**------------------del----------------------
	 *  多对多删除
	 * 1 、主控方直接删除
	 * 2、 被控方先通过主控方解除多对多关系,再删除被控方
	 * 3、 禁用级联删除  (会把三张表的数据都删掉)
	 */
	
	/**
	 * 1.主控方直接删除
	 * 
	 * 结果: 一并将表关联的中间表信息删除
	 */
	@Test
	public void testDel() {
		Book book = new Book();
		book.setBookId(6);
		this.bookDao.del(book);
	}
	
	/**
	 * 2.被控方先通过主控方解除多对多关系,再删除被控方
	 */
	
	
	/**
	 * 错误2:
	 * Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
	 * Cannot delete or update a parent row: a foreign key constraint fails 
	 * (`mybatis_ssm`.`t_hibernate_book_category`, CONSTRAINT `t_hibernate_book_category_ibfk_2` 
	 * FOREIGN KEY (`cid`) REFERENCES `t_hibernate_category` (`category_id`))
	 * 
	 * 解决方法:
	 * 这是报数据库的主外键连接的错误,如果你有删除的外键表的数据就要先删除主键表的数据
	 * 1.接触关联关系(先删除中间表所引用数据)
	 * 2.再去删除主表信息
	 */
	
	@Test
	public void testDel2() {
		Category category = new Category();
		category.setCategoryId(4);
		this.categoryDao.del(category);
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值