Hibernate关联映射(多对多)

数据库多对多

在学习或使用Hibernate框架前,大家或多或少都已经做过多对多关系处理以及了解,为什么这么说,举个很简单的例子,一本书可以有多种类别,一个书类别下不止一本书,那么这就是多对多关系.
对于这种关系的处理,在数据库中都会建立一个表进行桥接,例如:

书本表:
在这里插入图片描述
书籍类别表:
在这里插入图片描述

如果要给这两张表进行关联,体现多对多关系,就需要建立一个桥接表关联:
在这里插入图片描述
其中bid就是书本的id,cid就是类别id

Hibernate框架多对多增加

多对多的概念了解完,接下来说一下Hibernate的多对多关联映射,Hibernate主要就是在xml文件设置映射的关系了,建好实体类后,在xml中配置如下:

book.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.xiaoyang.entity.Book" table="t_book">
		<!-- id:用于设置数据库表结构中主键列的生成方式 name:实体类中属性名称 type:java中的数据类型 column:数据库表字段名称 -->
		<id name="bookId" type="java.lang.Integer" column="book_id">
			<!--class:定义主键列生成方式 hibernate管理 数据库管理 开发者管理 -->
			<generator class="identity"></generator>
		</id>
		<property name="bookName" type="java.lang.String" column="book_name" />
		<property name="price" type="java.lang.Float" column="price" />
		<!-- 建立映射的关联关系 -->
		<!-- name:当前映射文件实体类的集合属性 cascade:标明级联操作(例如update级联更新) inverse:是否执行级联操作 -->
		<set table="t_book_category" name="categories" cascade="save-update" inverse="false">
			<!-- 在哪个实体映射文件里面,key就是哪个 -->
			<!-- 外键列 -->
			<key column="bid"></key>
			<many-to-many column="cid" class="com.xiaoyang.entity.Category" />
		</set>
	</class>
</hibernate-mapping>

Category.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.xiaoyang.entity.Category" table="t_category">
		<!-- id:用于设置数据库表结构中主键列的生成方式 name:实体类中属性名称 type:java中的数据类型 column:数据库表字段名称 -->
		<id name="categoryId" type="java.lang.Integer" column="category_id">
			<!--class:定义主键列生成方式 hibernate管理 数据库管理 开发者管理 -->
			<generator class="identity"></generator>
		</id>
		<property name="categoryName" type="java.lang.String" column="category_name" />
		<!-- 建立映射的关联关系 -->
		<!-- name:当前映射文件实体类的集合属性 cascade:标明级联操作(例如update级联更新) inverse:是否执行级联操作 -->
		<set table="t_book_category" name="books" cascade="save-update" inverse="true">
			<!-- 在哪个实体映射文件里面,key就是哪个 -->
			<!-- 外键列 -->
			<key column="cid"></key>
			<many-to-many column="bid" class="com.xiaoyang.entity.Book" />
		</set>
	</class>
</hibernate-mapping>

值得一提的是,三张表只需建立两个实体类以及对应的映射文件即可,至于中间表,只需在映射文件中进行主控方和被控方设置,也就是inverse属性,如果是true则代表由对方控制,是被控方,false则代表不由对方控制,为主控方。这里是book表为主动方进行维护关联关系!

封装好的session工厂类:

package com.xiaoyang.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * 
 * @author xiaoyang
 *
 */
public class SessionFactoryUtils {

	private static final String 
			HIBERNATE_CONFIG_FILE="hibernate.cfg.xml";
	
	private static ThreadLocal<Session> threadLocal=
			new ThreadLocal<Session>();
	
	//创建数据库的会话工厂
	private static SessionFactory sessionFactory;
	
	//读取hibernate核心配置
	private static Configuration configuration;
	
	static {
		try {
			configuration=new Configuration();
			configuration.configure(HIBERNATE_CONFIG_FILE);
			//创建Session会话工厂
			sessionFactory=configuration.buildSessionFactory();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static Session openSession() {
		Session session = threadLocal.get();
		if(null==session) {
			session=sessionFactory.openSession();
			threadLocal.set(session);
		}
		return session;
	}
	
	public static void closeSession() {
		Session session = threadLocal.get();
		if(null!=session) {
			if(session.isOpen())
				session.close();
			threadLocal.set(null);
		}
	}
	
	public static void main(String[] args) {
		Session session = SessionFactoryUtils.openSession();
		System.out.println("Session状态:"+session.isOpen());
		System.out.println("Session会话已打开");
		SessionFactoryUtils.closeSession();
		System.out.println("Session会话已关闭");
	}
}

增加方法:

public void save(Book book) {
		Session session=SessionFactoryUtils.openSession();
		Transaction ts = session.beginTransaction();
		session.save(book);
		ts.commit();
		SessionFactoryUtils.closeSession();
	}

junit测试:


	//增加
	public void testSave() {
		book.setBookName("java");
		book.setPrice(99f);

		category.setCategoryId(2);
		category.setCategoryName("编程");
		// book.setCategories(categories);
		book.getCategories().add(category);
		bookDao.save(book);
	}

书籍类别表:
在这里插入图片描述
书籍表:
在这里插入图片描述
中间表:

在这里插入图片描述

Hibernate多对多删除

多对多删除和增加大同小异,主要要注意的就是主控方和被控方的一个操纵,主控方直接进行删除操作即可,被控方则需要解除关联关系才能进行删除,下面就直接上代码了:

主控方删除:

	// 主控制方:直接删除
	public void testDel() {
		book.setBookId(6);
		bookDao.del(book);
	}

被控方删除

// 被控制方:先解除关联关系再删除
		public void testDelcate() {
			category.setCategoryId(3);
			categoryDao.del(category);
		}

del方法:

		public void del(Category category) {
		Session session=SessionFactoryUtils.openSession();
		Transaction ts = session.beginTransaction();
		Category c = session.get(Category.class,category.getCategoryId());
		if(null!=c) {
		//如果按照id查询内容不为空,则表明有关联关系,进行遍历删除解除关联关系
			for (Book b : c.getBooks()) {
				b.getCategories().remove(c);
			}
			session.delete(c);
		}
		ts.commit();
		SessionFactoryUtils.closeSession();
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值