数据库的多对多
1.1 数据库中不能直接映射多对多
处理:创建一个桥接表(中间表),将一个多对多关系转换成两个一对多
注1:数据库多表联接查询
永远就是两个表的联接查询
注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可以直接映射多对多关联关系(看作两个一对多)
案例:
多对多级联查询 书籍表、书籍类别表
实体类:
书 :book
类型:category
一本书对应多种类型 ,一种类型有多本书
Book
package com.zking.five.entity;
import java.util.HashSet;
import java.util.Set;
public class Book {
private Integer bookId;
private String bookName;
private float price;
private Set<Category> categroies=new HashSet<>();
private Integer initCategroies=0;
public Integer getInitCategroies() {
return initCategroies;
}
public void setInitCategroies(Integer initCategroies) {
this.initCategroies = initCategroies;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Set<Category> getCategroies() {
return categroies;
}
public void setCategroies(Set<Category> categroies) {
this.categroies = categroies;
}
}
Category
package com.zking.five.entity;
import java.util.HashSet;
import java.util.Set;
public class Category {
private Integer categoryId;
private String categoryName;
private Set<Book> books=new HashSet<>();
private Integer initbooks=0;
public Integer getInitbooks() {
return initbooks;
}
public void setInitbooks(Integer initbooks) {
this.initbooks = initbooks;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public Set<Book> getBooks() {
return books;
}
public void setBooks(Set<Book> books) {
this.books = books;
}
}
映射类 (体现关系)
Book.hbml.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 通过查询一本书 查出关联的所有类别 的原理:
session.get(Book.class, 1); =select * from t_hibernate_book where book_id=?(1)
resultSet -> 1 西游记 50
Book b=Class.forName("com.zking.five.entity.Book").newInstance(); //空的
b.setBookId(1);
b.setBookName(西游记);
b.setPrice(50);
hibernate处理关联关系
1 .通过set找到桥接表 (table属性),
2.找到 当前实体类对应表 的主键 在桥接表中的外键(key 标签中的column属性)
3.查出关联表(t_hibernate_category)的主键 (category_id)
select cid from t_hibernate_book_category where bid=? (1)
resultSet -> 1 2
list<String>1/2
4.查出来的外键关联了一个实体类 (class="com.zking.five.entity.Category"),他可以找到这个类的映射文件( class标签的name="com.zking.five.entity.Category"),
从而找到了对应的实体类对应的表的主键id标签中的column字段 ->category_id
select * from t_hibernate_category where t_hibernate_category in (1,2)
resultSet-> 1 古典
2 神话
Category c=Class.forName("com.zking.five.entity.Category").newInstance();
原理参照EntityBaseDao ->List<c> -> categories
5.b.setcategoyies(categories);
-->
<class table="t_hibernate_book" name="com.zking.five.entity.Book">
<id name="bookId" type="java.lang.Integer" column="book_id">
<generator class="increment"></generator>
</id>
<property name="bookName" type="java.lang.String" column="book_name" ></property>
<property name="price" type="java.lang.Float" column="price" ></property>
<!--table 桥接表 -->
<set table="t_hibernate_book_category" name="categroies" cascade="save-update" inverse="false">
<!-- one 书-->
<key column="bid"></key>
<!-- many 类别-->
<many-to-many column="cid" class="com.zking.five.entity.Category"></many-to-many>
</set>
</class>
</hibernate-mapping>
Category.hbml.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class table="t_hibernate_category" name="com.zking.five.entity.Category">
<id name="categoryId" type="java.lang.Integer" column="category_id">
<generator class="increment"></generator>
</id>
<property name="categoryName" type="java.lang.String" column="category_name" ></property>
<!--table 桥接表 -->
<set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
<!-- one 类别-->
<key column="cid"></key>
<!-- many 书-->
<many-to-many column="bid" class="com.zking.five.entity.Book"></many-to-many>
</set>
</class>
</hibernate-mapping>
查询的方法
package com.zking.five.dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.zking.five.entity.Book;
import com.zking.two.util.SessionFactoryUtil;
public class BookDao {
public Book getBook(Book book) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Book b= session.get(Book.class, book.getBookId());
if(b!=null&&new Integer(1).equals(book.getInitCategroies())) {
Hibernate.initialize(b.getCategroies());
}
transaction.commit();
SessionFactoryUtil.closeSession();
return b;
}
}
package com.zking.five.dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.zking.five.entity.Category;
import com.zking.two.util.SessionFactoryUtil;
public class CategoryDao {
public Category getCategory(Category category) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategoryId());
if(c!=null&&new Integer(1).equals(category.getInitbooks())) {
Hibernate.initialize(c.getBooks());
}
transaction.commit();
SessionFactoryUtil.closeSession();
return c;
}
}
测试
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();
/**
* 通过查询一本书 查出关联的所有类别
*/
@Test
public void testGetBook() {
Book book=new Book();
book.setInitCategroies(1);//强制加载
book.setBookId(1);
Book b = this.bookDao.getBook(book);
System.out.println(b.getBookName());//书名
for (Category c : b.getCategroies()) {
System.out.println(c.getCategoryName());//类别
}
}
}
package com.zking.five.dao;
import static org.junit.Assert.*;
import org.junit.Test;
import com.zking.five.entity.Book;
import com.zking.five.entity.Category;
public class CategoryDaoTest {
private CategoryDao categoryDao=new CategoryDao();
/**
* 通过查询一个类别 查出关联的所有书籍
*/
@Test
public void testGetCategory() {
Category category=new Category();
category.setCategoryId(3);
category.setInitbooks(1);
Category c = this.categoryDao.getCategory(category);
System.out.println(c.getCategoryName());
for (Book b : c.getBooks()) {
System.out.println(b.getBookName());
}
}
}