什么是多对多关系呢?
关系数据库中两个表之间的一种关系, 该关系中第一个表中的一个行可以与第二个表中的一个或多个行相关。第二个表中的一个行也可以与第一个表中的一个或多个行相关。
比如在常见的订单管理数据库当中“产品”表和“订单”表之间的关系。单个订单中可以包含多个产品。另一方面,一个产品可能出现在多个订单中。
要表示多对多关系,就妖创建第三个表,称为 联接表,也称( 桥接表、中间表)。它多对多关系分Wie两个一对多关系。将连个主键都放在第三个表中,因此,第三个表记录关系的每个匹配项或实例。
不多说,我们实例来战:嘻嘻嘻
Example1:自关联查询 树形菜单表
TreeNode.jsp ,实现set/get方法
当前节点对父节点 多对一
父节点对子节点 一对多
entiey类
private Integer treeNodeId;
private String treeNodeName;
private Integer treeNodeType;
private Integer position;
private String url;
// private Set children = new HashSet();//一对多
private List children = new ArrayList();//一对多,用List是为了可以排序
private TreeNode parent;//外键 多对多
private Integer IntiChildren = 0;
写TreeNode.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- <set name="children" cascade="save-update" inverse="true">
<key column="parent_node_id"></key>
<one-to-many class="com.zking.five.entity.TreeNode"/>
</set> -->
<!--bag 用于排序 order-by 指的是数据库中的表字段 -->
<bag order-by="position" name="children" cascade="save-update" inverse="true">
<key column="parent_node_id"></key>
<one-to-many class="com.zking.five.entity.TreeNode"/>
</bag>
<many-to-one name="parent" class="com.zking.five.entity.TreeNode" column="parent_node_id"/>
</class>
写一个简单的dao
package com.zking.five.dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.zking.five.entity.TreeNode;
import com.zking.two.util.SessionFactoryUtils;
public class TreeNodeDao {
public TreeNode get(TreeNode treeNode) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
TreeNode tn = session.get(TreeNode.class, treeNode.getTreeNodeId());
if(tn !=null && new Integer(1).equals(treeNode.getIntiChildren())) {
Hibernate.initialize(tn.getChildren());
}
// System.out.println(tn);
transaction.commit();
session.close();
return tn;
}
}
用Junit测试
package com.zking.five.dao;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import com.zking.five.entity.TreeNode;
public class TreeNodeDaoTest {
private TreeNodeDao treeNodeDao =new TreeNodeDao();
@Before
public void setUp() throws Exception {
}
@Test
public void testGet() {
TreeNode treeNode = new TreeNode();
treeNode.setTreeNodeId(1);
treeNode.setIntiChildren(1);
TreeNode tn = this.treeNodeDao.get(treeNode);
System.out.println(tn.getTreeNodeId()+","+tn.getTreeNodeName());
for(TreeNode tn2 : tn.getChildren()) {
System.out.println(tn2.getTreeNodeId()+","+tn2.getTreeNodeName());
}
}
}
这样的原理是:
当加载一级节点时,ok
加载二级节点时,由于设置了强制加载,但同样可以加载所有的二级节点,ok
加载三级节点时,session关闭,并且默认采用的是懒加载
权限菜单加载有两种方式
1.一次性将数据库中的数据全部加载往浏览器返回(适用于菜单较少)
2、菜单表数据量较大,当出现浏览器卡顿的情况,第一种方式就不在使用。
采用第二种:菜单逐级加载。
Example2: 多对多级联查询 书籍表、书籍类别表
书籍可以对应多个类别,而类别也可以对应多本书,所以是多对多的关系。
Book表的主键:book_id category类别表的主键:category_id 而他们在连接表分别的主键是bid和cid
在Book.hbm.xml配置文件中 通过自动关联联接表,以及关联查询出关联对象。
<!-- 自动关联桥接表 -->
<set table="t_hibernate_book_category" name="categorys" cascade="save-update" inverse="false">
<!--one bid 代表的是一对多的关系,也就是书籍对应的多个类别-->
<key column="bid"></key>
<!-- many cid代表的是多对多的关系 去查类别表-->
<many-to-many column="cid" class="com.zking.five.entity.Category"/>
</set>
</class>
类别表的配置文件也是同一个道理
<?xml version="1.0" encoding="UTF-8"?>
<set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
<key column="cid"></key>
<many-to-many column="bid" class="com.zking.five.entity.Book"/>
</set>
</class>
总结:
在hibernate中,你只管查询当前表对象即可