重点:
1、级联新增 inverse属性值的设置
2、 级联删除
重点解析:
1.hibernate的多对多
1.1 hibernate可以直接映射多对多关联关系(看作两个一对多)
讲解inverse;
总共四种 (false 是控制方 ,true 是被控制方),其中有两种正确,两种错误
- 1、book:false category:true ✓(代表意思是:将维护的责任交给book)
- 2、book: true category:false ✓
- 3、book:true category:true ✗
- 4、book:false category:false ✗
多对多关系注意事项
2.1 一定要定义一个主控方
2.2 多对多删除
2.2.1 主控方直接删除
2.2.2 被控方先通过主控方解除多对多关系,再删除被控方
2.2.3 禁用级联删除
2.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护
这是是dao方法的增加(之前的实体类还有配置文件在前几天发布了)
// 书籍新增
public Integer add(Book book) {
Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Integer bid = (Integer) session.save(book);
transaction.commit();
session.close();
return bid;
}
//书籍删除
public void del(Book book) {
Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.delete(book);
transaction.commit();
session.close();
}
// 书籍类型 新增
public Integer save(Category category) {
Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Integer cid = (Integer) session.save(category);
transaction.commit();
session.close();
return cid;
}
/**
* 因为被控方被中间表所引用
* 1、触发关联关系(主控方解除多对多关系)
* 2、删除主控方的相关数据
*
* @param category
*/
// 书籍类型删除
public void del(Category category) {
Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory sessionFactory = configure.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategoryId());
//c 里面保存着与某一些书籍相关联的关系
for (Book b : c.getBooks()) {
//注意:关系交于book维护
// c.getBooks().remove(b); 这是错误的
b.getCategories().remove(c);
}
session.delete(c);
transaction.commit();
session.close();
}
测试的方法,代码分享:
/**----------------------------------six---------------------------
*- 提交书本信息,勾选复选框类别, 提交
* jdbc: bookDao.add,bookCategoryDao.add
* hibernate : bookDao.add
*
* 讲解inverse;
* 总共四种 (false 是控制方 ,true 是被控制方),其中有两种正确,两种错误
* 1、book:false category:true ✓(代表意思是:将维护的责任交给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 = new Book();
book.setBookName("颤抖吧!ET");
book.setPrice(66F);
//这是错误的示范
Category category = new Category();
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))
* 2、book: true category: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、 被控方先通过主控方解除多对多关系,再删除被控方
*/
/*
* 主控方直接删除
* 结论: 一并将从表关联的中间表信息删除
*/
@Test
public void testDel() {
Book book = new Book();
book.setBookId(5);
this.bookDao.del(book);
}
/*
* 被控方先通过主控方解除多对多关系,再删除被控方
*/
/**
* 错误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`))
*
* 解决方法:
* 这是报数据库的主外键连接的错误,如果你有删除的外键表的数据就要先删除主键表的数据
*/
@Test
public void testDel2() {
Category category = new Category();
category.setCategoryId(1);
this.categoryDao.del(category);
}