1. 数据库的多对多
1.1 数据库中不能直接映射多对多
处理:创建一个桥接表(中间表),将一个多对多关系转换成两个一对多
注1:数据库多表联接查询
永远就是二个表的联接查询
A B C D
t1 C
t2 D
t3
注2:交叉连接
注3:外连接:left(左)/right(右)/full(左右)
主从表:连接条件不成立时,主表记录永远保留,与null匹配
A B AB
select * from A,B,AB WHERE A.aID=AB.aID and b.bid = AB.bid
where
在hibernate中,你只管查询当前表对象即可,
hibernate会字段关联桥表以及关联表查询出关联对象
2. hibernate的多对多
2.1 hibernate可以直接映射多对多关联关系(看作两个一对多)
3. 多对多关系注意事项
3.1 一定要定义一个主控方
3.2 多对多删除
3.2.1 主控方直接删除
3.2.2 被控方先通过主控方解除多对多关系,再删除被控方
3.2.3 禁用级联删除(可能会导致所有表数据被清空,cascade尽量设置save-update即可)
3.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护
package com.company.five.dao;
import java.io.Serializable;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.company.five.entity.Book;
import com.company.five.entity.Category;
import com.company.two.util.SessionFactoryUtils;
public class BookDao {
public Book getBook(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Book b = session.get(Book.class, book.getBookId());
if(b != null && new Integer("1").equals(book.getInitBook())) {
Hibernate.initialize(b.getCategorys());
}
transaction.commit();
session.close();
return b;
}
public Category getCategory(Category c) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Category ca = session.get(Category.class, c.getCategoryId());
if(c != null && new Integer("1").equals(c.getInitCate())) {
Hibernate.initialize(ca.getBooks());
}
transaction.commit();
session.close();
return ca;
}
/**
* ------------------------------------------six----------------------------------------
*
*/
public Integer add(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Integer e = (Integer) session.save(book);
transaction.commit();
session.close();
return e;
}
public Integer add2(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Integer e = (Integer) session.save(category);
transaction.commit();
session.close();
return e;
}
public void del(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
session.delete(book);
transaction.commit();
session.close();
}
/**
* 删除被控方的数据步骤
* 1,被控方通过主控方来接触关联关系
* 2,再去删除被控方
* @param category
*/
public void del(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategoryId());
for (Book b : c.getBooks()) {
//通过主控方删除关联关系
b.getCategorys().remove(c);
}
session.delete(c);
transaction.commit();
session.close();
}
}
package com.company.five.dao;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import com.company.five.entity.Book;
import com.company.five.entity.Category;
public class BookDaoTest {
BookDao bookDao = new BookDao();
@Before
public void setUp() throws Exception {
}
@Test
public void testGetBook() {
Book book = new Book();
book.setBookId(4);
book.setInitBook(1);
Book b = bookDao.getBook(book);
for (Category c : b.getCategorys()) {
System.out.println(c.getCategoryName());
}
}
@Test
public void testGetCategory() {
Category category = new Category();
category.setCategoryId(1);
category.setInitCate(1);
Category c = bookDao.getCategory(category);
for (Book b : c.getBooks()) {
System.out.println(b.getBookName());
}
}
/**
* ------------------------------------------six----------------------------------------
*
*
* 级联新增:
*
* 1.
* book.hbm.xml : inverse=false
* category.hbm.xml : inverse=true
*
* inverse : 反方
*
* 指的是将级联关系的维护的责任交给book对象。
*
*
* jdbc:
* this.bookDao.add 书籍表增加
* this.bookCategoryDao.add 中间表增加
*
* hibernate
* this.bookDao.add
*
* 在多对多的关系维护中,hibernate管理的是持久态对象。
*
*
* 2.当关系双方的inverse都是设置为false时中间表会出现两条数据,添加了两次
* 在实际开发中中间表的主键一般是两个外键的组合所以一般不会出现这个问题
*
* 3.当双方的inverse都是false时增加时中间表不会增加
*
*
* 小结:
* 设置inverse的属性:
* 1,一方为false,一方为true当增加设置false的一方的表时因为设置它管理关系所以中间表会自动增加
* 另一方因为不管理关系所以增加这个表时中间表数据不会自动增加
* 2,当双方为false时,双方都管理关系所以中间表都会自动增加但是会增加重复 (部分版本(如:5.3.6.Final版本)不会重复增加)
* 3,当双方都为true时,说明双方都不管理关系所以无论增加哪一方都不会在中间表中增加数据
*/
@Test
public void testAdd1() {
Book book = new Book();
book.setBookName("不死不灭222");
book.setPrice(12f);
Category category = new Category();
category.setCategoryId(7);
book.getCategorys().add(bookDao.getCategory(category));
Integer add = bookDao.add(book);
System.out.println(add);
}
/**
* 添加一个新的类别,绑定原有的某个书籍
*/
@Test
public void testAdd2() {
Category category = new Category();
category.setCategoryName("科幻");
Book book = new Book();
book.setBookId(7);
category.getBooks().add(bookDao.getBook(book));
Integer add2 = bookDao.add2(category);
System.out.println(add2);
}
/**
* 主控方删除
* 需求:删除有关联关系的一本书
*
*/
@Test
public void testDel1() {
Book book = new Book();
book.setBookId(7);
this.bookDao.del(book);
}
@Test
public void testDel2() {
Category category = new Category();
category.setCategoryId(7);
this.bookDao.del(category);
}
}