1. 数据库的多对多
数据库中不能直接映射多对多
处理:创建一个桥接表(中间表),将一个多对多关系转换成两个一对多
注1:数据库多表联接查询
永远就是二个表的联接查询
2. hibernate的多对多
hibernate可以直接映射多对多关联关系(看作两个一对多)
3. 多对多关系注意事项
3.1 一定要定义一个主控方
3.2 多对多删除
3.2.1 主控方直接删除
3.2.2 被控方先通过主控方解除多对多关系,再删除被控方
3.2.3 禁用级联删除
3.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护
/**
* 1.被控方通过主控方来解除关联关系
* 2.再次删除被控方
* @param cateGory
*/
public void del(CateGory cateGory) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
CateGory c = session.get(CateGory.class,cateGory.getCategoryId());
for(Book b:c.getBooks()) {
// c.getBooks().remove(b);
b.getCategories().remove(c);
}
session.delete(c);
transaction.commit();
session.close();
}
级联新增test:
/**
* 级联新增
* book.hbm.xml:inverse=false
* category.hbm.xml:inverse=true
* inverse:反方
* 指的是将级联关系的维护的责任交给book对象
*
* jdbc:
* this.bookDao.add
* this.bookCategoryDao.add
*
* hibernate
* this.bookdao.add
* 在多对多的关系维护中,hibernate管理的是持久化对象
*/
@Test
public void testAdd1() {
Book book = new Book();
book.setBookName("不死不灭");
book.setPrice(45f);
CateGory cateGory = new CateGory();
cateGory.setCategoryId(2);
book.getCategories().add(this.categoryDao.get(cateGory));
this.bookDao.add(book);
}
自关联案例:
dao方法:
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.getInitChildren())) {
Hibernate.initialize(tn.getChildren());
}
// System.out.println(tn);
transaction.commit();
session.close();
return tn;
}
xml:
<hibernate-mapping>
<class table="t_hibernate_sys_tree_node" name="com.zking.five.entity.TreeNode">
<id name="treeNodeId" type="java.lang.Integer" column="tree_node_id">
<generator class="increment"></generator>
</id>
<property name="treeNodeName" type="java.lang.String" column="tree_node_name"></property>
<property name="treeNodeType" type="java.lang.Integer" column="tree_node_type"></property>
<property name="position" type="java.lang.Integer" column="position"></property>
<property name="url" type="java.lang.String" column="url"></property>
<!-- <set name="children" cascade="save-update" inverse="true">
<key column="parent_node_id"></key>
<one-to-many class="com.zking.five.entity.TreeNode"></one-to-many>
</set> -->
<!--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"></one-to-many>
</bag>
<many-to-one name="parent" class="com.zking.five.entity.TreeNode" column="parent_node_id"></many-to-one>
</class>
</hibernate-mapping>
test:
@Test
public void testGet() {
TreeNode treeNode = new TreeNode();
treeNode.setTreeNodeId(1);
treeNode.setInitChildren(1);
TreeNode tn = this.treeNodeDao.get(treeNode);
// System.out.println(tn);
System.out.println(tn.getTreeNodeId()+","+tn.getTreeNodeName());
for(TreeNode tn2:tn.getChildren()) {
System.out.println(tn2.getTreeNodeId()+","+tn2.getTreeNodeName());
}
/**
* 当加载一级节点的时候没问题
* 加载二级的时候。由于设置了强制加载,同样可以加载二级节点,没问题。
* 加载三级节点这时session关闭了,并且默认查出的节点,是默认采用的懒加载
*
*
* 权限菜单加载有两种方式
* 1.一次性将数据库的数据全部加载往浏览器返回(是用于菜单较少)
* 2.菜单表数据量较大,当出现浏览器卡顿的情况,第一种方式就不再适用
* 那么采用菜单逐级加载
*/
}