hibernate多对多关联关系
程序员文章站
2022-07-05 23:44:24
文章目录多对多概念hibernate的多对多多对多关系注意事项代码案例多对多概念首先我们来说一下多对多的概念,可以这么理解一个人可以对应多个项目,一个项目可以对应多个人,多对多可以看做是两个一对多。hibernate的多对多数据库中不能直接映射多对多,hibernate可以直接映射多对多关联关系(看作两个一对多) ,我们需要创建一个桥接表(中间表),将一个多对多关系转换成两个一对多。这里是创建了三个表,关于书籍的,一本书对应多个类型,类型可以对应多本书。多对多关系注意事项一定要定义一个主控...
文章目录
多对多
概念
首先我们来说一下多对多的概念,可以这么理解一个人可以对应多个项目,一个项目可以对应多个人,多对多可以看做是两个一对多。
hibernate的多对多
数据库中不能直接映射多对多,hibernate可以直接映射多对多关联关系(看作两个一对多) ,我们需要创建一个桥接表(中间表),将一个多对多关系转换成两个一对多。
这里是创建了三个表,关于书籍的,一本书对应多个类型,类型可以对应多本书。
多对多关系注意事项
一定要定义一个主控方 有且只有一个,如果是两个主控方的话会造成数据的重复插入。
多对多删除
- 主控方直接删除
- 被控方先通过主控方解除多对多关系,再删除被控方
- 禁用级联删除
讲解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