数据库多对多
在学习或使用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();
}