hibernate多对多关联关系

2022-07-31,

文章目录

    • 多对多
      • 概念
      • hibernate的多对多
      • 多对多关系注意事项
    • 代码案例

多对多

概念

首先我们来说一下多对多的概念,可以这么理解一个人可以对应多个项目,一个项目可以对应多个人,多对多可以看做是两个一对多

hibernate的多对多

数据库中不能直接映射多对多,hibernate可以直接映射多对多关联关系(看作两个一对多) ,我们需要创建一个桥接表(中间表),将一个多对多关系转换成两个一对多。

这里是创建了三个表,关于书籍的,一本书对应多个类型,类型可以对应多本书。

多对多关系注意事项

一定要定义一个主控方 有且只有一个,如果是两个主控方的话会造成数据的重复插入。

多对多删除

  1. 主控方直接删除
  2. 被控方先通过主控方解除多对多关系,再删除被控方
  3. 禁用级联删除

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

代码案例

关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护

book实体关系配置

<?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 name="com.liyingdong.entity.Book" table="t_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 name="price" type="java.lang.Float" column="price"/>
		
			<!-- 建立关联关系     注:级联删除不建议使用(cascade:delete)-->
			<!-- inverse:把对方设置为主控方  -->
			<!-- cascade:save-update:级联保存或者更新 -->
			<set table="t_book_category" name="categories" inverse="false"  cascade="save-update,delete" >
			<!--在那个实体映射文件里面  -->
			<!-- one -->
			<key column="bid"></key><!-- 外键列 -->
			<!-- 多方 -->
			 <many-to-many column="cid" class="com.liyingdong.entity.Category"></many-to-many>
			</set>
		</class>
		
	</hibernate-mapping>

Category.hbm.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 name="com.liyingdong.entity.Category" table="t_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"/>
		
			<!-- 建立关联关系     注:级联删除不建议使用(cascade:delete)-->
			<!-- inverse:把对方设置为主控方  -->
			<!-- cascade:save-update:级联保存或者更新 -->
			<set table="t_book_category" name="books" inverse="true"  cascade="save-update" >
			<!--在那个实体映射文件里面  那个就是一方-->
			<!-- one -->
			<key column="cid"></key><!-- 外键列 -->
			<!-- 多方 -->
			 <many-to-many column="bid" class="com.liyingdong.entity.Book"></many-to-many>
			</set>
		</class>
		
	</hibernate-mapping>

OrderItem.hbm.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 name="com.liyingdong.entity.OrderItem" table="t_order_item">
			<id name="orderItemId" type="java.lang.Integer" column="order_item_id">
				<generator class="increment"></generator>
			</id>
			<!-- 与实体类相匹配 -->
			<property name="productId" type="java.lang.Integer" column="product_id"/>
			<property name="quantity" type="java.lang.Integer" column="quantity"/>
			 <!--1.注释 2.只读-->
			<property name="oid" type="java.lang.Integer" column="oid"  insert="false" update="false"  />
			<!-- 多对一关联关系  放置的是一方的对象 -->
			<!-- 
			name      :一方的对象的属性名称
			class     :一方的类的全路劲
			column    :在多方的表的外键的名称
			 -->
			 <!-- 从many到one的方向:操作many对象能同时操作one对象  -->
			<many-to-one name="order" class="com.liyingdong.entity.Order" column="oid"/>
		</class>
	</hibernate-mapping>

CategoryDao类别

级联删除一般不用或者说是禁用的,被控方删除的话是需要先解除关系的然后在删除。

package com.liyingdong.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.liyingdong.entity.Book;
import com.liyingdong.entity.Category;
import com.liyingdong.util.SessionFactoryUtils;

public class CategoryDao {
	
	
    //被控方删除
	public void del(Category cate) {
		Session session = SessionFactoryUtils.openSession();
		Transaction ts = session.beginTransaction();
	    //CRUD
		Category c = session.get(Category.class, cate.getCategoryId());
		//解除关联关系
		if(null!=c) {
			for(Book b : c.getBooks()) {
				b.getCategories().remove(c);
			}
			session.delete(c);
		}
		
		ts.commit();
		SessionFactoryUtils.closeSession();
		
	}
}

bookDao(主控方增加、删除)

package com.liyingdong.dao;

import java.io.Serializable;

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

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

import com.liyingdong.entity.Book;
import com.liyingdong.entity.Order;
import com.liyingdong.util.SessionFactoryUtils;

public class BookDao {

	
	public void save(Book book) {
			
			Session session = SessionFactoryUtils.openSession();
			Transaction ts = session.beginTransaction();
			
			//CRUD
			session.save(book);
			
			ts.commit();
			SessionFactoryUtils.closeSession();
		}
	
	public void del(Book book) {
		Session session = SessionFactoryUtils.openSession();
		Transaction ts = session.beginTransaction();
	    //CRUD
		Book b = session.get(Book.class, book.getBookId());
		if(null!=b) {
			session.delete(b);
		}
		
		ts.commit();
		SessionFactoryUtils.closeSession();
		
	}
}		

Juint测试

package com.liyingdong.dao;

import static org.junit.Assert.*;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Before;
import org.junit.Test;

import com.liyingdong.entity.Book;
import com.liyingdong.entity.Category;
import com.liyingdong.util.SessionFactoryUtils;

public class BookDaoTest {

	Book book=null;
	Category cate=null;
	BookDao bd=new BookDao();
	CategoryDao cd=new CategoryDao();
	
	@Before
	public void setUp() throws Exception {
		cate=new Category();
		book=new Book();
	}

	@Test
	public void testSave() {
		book.setBookName("富婆如何爱上我");
		book.setPrice(137f);
		
		cate.setCategoryId(1);
		cate.setCategoryName("古典");
		book.getCategories().add(cate);
		
		bd.save(book);
	}

	//主控方直接删除
	@Test
	public void testDel() {
		book.setBookId(1);
		bd.del(book);
	}
	
	//被主控:方解除关系删除
	@Test
	public void testDel2() {
		cate.setCategoryId(2);
		cd.del(cate);
	}
	
}

本文地址:https://blog.csdn.net/qq_45384482/article/details/107669408

《hibernate多对多关联关系.doc》

下载本文的Word格式文档,以方便收藏与打印。