hibernate 多对多,多对多级联查询

本文探讨了数据库中多对多关系的处理方法,通常需要创建桥接表来转换为一对多关系。在Hibernate中,可以实现多对多的直接映射,例如在书籍表和类别表的案例中。通过Hibernate的映射文件,可以实现多对多级联查询,查询时只需关注当前表对象,Hibernate会自动处理关联。测试中展示了如何在实体类Book和Category以及它们的映射文件中设置这种关系。

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

数据库的多对多
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());
		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值