2018-10-25 hibernate多对多

xiaoxiao2025-10-15  4

1. 数据库的多对多

1.1 数据库中不能直接映射多对多 处理:创建一个桥接表(中间表),将一个多对多关系转换成两个一对多 注1:数据库多表联接查询 永远就是二个表的联接查询 注2:交叉连接 注3:外连接:left(左)/right(右)/full(左右) 主从表:连接条件不成立时,主表记录永远保留,与null匹配 A B AB select * from A,B,AB WHERE A.aID=AB.aID and b.bid = AB.bid where 在hibernate中,你只管查询当前表对象即可, hibernate会自动关联桥表以及关联表查询出关联对象 Book Category Book_category select * from Book b,Book_category bc,category where b.bid = bc.bid and bc.cid = c.cid and bid = 2

2. hibernate的多对多

2.1 hibernate可以直接映射多对多关联关系(看作两个一对多)

3. 多对多关系注意事项

3.1 一定要定义一个主控方 3.2 多对多删除 3.2.1 主控方直接删除 3.2.2 被控方先通过主控方解除多对多关系,再删除被控方 3.2.3 禁用级联删除 3.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护

hibernate一对多简易权限设计

实体类TreeNode

private Integer treeNodeId; private String treeNodeName; private Integer treeNodeType; private Integer position; private String url; //当前节点与节点的关联关系 一对多 set里放自定义的类是无序的 // private Set<TreeNode> children = new HashSet<TreeNode>(); private List<TreeNode> children = new ArrayList<TreeNode>(); //当前节点与父节点的关系 多对一 private TreeNode parent; //强制初始化 private Integer initChildren = 0; 提供set/get方法

treenode.hbm.xml

<class table="t_hibernate_sys_tree_node" name="com.test.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.test.five.entity.TreeNode"/> </set> --> <!-- 排序 order-by指的是数据库中的表字段 list有序列表 set中的类是自定义的则是无序的 --> //bag相当于list <bag order-by="position" name="children" cascade="save-update" inverse="true"> <key column="parent_node_id"></key> <one-to-many class="com.test.five.entity.TreeNode"/> </bag> <many-to-one name="parent" class="com.test.five.entity.TreeNode" column="parent_node_id"></many-to-one> </class>

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; }

test

private TreeNodeDao treeNodeDao = new TreeNodeDao(); @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、菜单表数据量较大,当出现浏览器卡顿的情况,第一种方式就不再使用了。 * 那么咱们就采用逐级加载(相当于异步) */

多对多案例

entity

//Book private Integer bookId; private String bookName; private Float price; //一本书对应多个类别 private Set<Category> categories = new HashSet<Category>(); private Integer initCategories = 0; public Integer getInitCategories() { return initCategories; } public void setInitCategories(Integer initCategories) { this.initCategories = initCategories; } public Set<Category> getCategories() { return categories; } public void setCategories(Set<Category> categories) { this.categories = categories; } public Integer getBookId() { return bookId; } public void setBookId(Integer bookId) { this.bookId = bookId; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } //category private Integer categoryId; private String categoryName; private Set<Book> books = new HashSet<Book>(); private Integer initBooks = 0; public Integer getInitBooks() { return initBooks; } public void setInitBooks(Integer initBooks) { this.initBooks = initBooks; } public Set<Book> getBooks() { return books; } public void setBooks(Set<Book> books) { this.books = books; } public Integer getCategoryId() { return categoryId; } public void setCategoryId(Integer categoryId) { this.categoryId = categoryId; } public String getCategoryName() { return categoryName; } public void setCategoryName(String categoryName) { this.categoryName = categoryName; }

配置文件

//book.hbm.xml <class table="t_hibernate_book" name="com.test.five.entity.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> <property name="price" type="java.lang.Float" column="price"></property> <set table="t_hibernate_book_category" name="categories" cascade="save-update" inverse="false"> <!-- 主键关联的外键 --> <!-- one --> <key column="bid"></key><!-- 通过bid找到cid对应的类别 --> <!-- many --> <many-to-many column="cid" class="com.test.five.entity.Category"></many-to-many> </set> </class> //category.hbm.xml <class table="t_hibernate_category" name="com.test.five.entity.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"></property> <set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true"> <key column="cid"></key> <many-to-many column="bid" class="com.test.five.entity.Book"></many-to-many> </set> </class>

dao

public Book get(Book book) { Session session = SessionFactoryUtils.getSession(); Transaction transaction = session.beginTransaction(); Book b = session.get(Book.class, book.getBookId()); if(b!=null&&new Integer(1).equals(book.getInitCategories())) { Hibernate.initialize(b.getCategories()); } transaction.commit(); session.close(); return b; } public Category get(Category category) { Session session = SessionFactoryUtils.getSession(); Transaction transaction = session.beginTransaction(); Category c = session.get(Category.class, category.getCategoryId()); if(c!=null&&new Integer(1).equals(category.getInitBooks())) { Hibernate.initialize(c.getBooks()); } transaction.commit(); session.close(); return c; }

test

/** * 通过一本书能够查询到多个类别 * jdbc:三表联查 * hibernate:只需要查询单个对象即可,它是自动关联查询,交给映射文件即可 */ @Test public void testGet1() { Book book = new Book(); book.setBookId(5); book.setInitCategories(1); Book b = this.bookDao.get(book); System.out.println(b.getBookName()); for(Category c:b.getCategories()) { System.out.println(c.getCategoryName()); } } /** * 通过一个类别查询多个类别 */ @Test public void testGet2() { Category category = new Category(); category.setCategoryId(1); category.setInitBooks(1); Category c = this.categoryDao.get(category); System.out.println(c.getCategoryName()); for(Book b :c.getBooks()) { System.out.println(b.getBookName()); } }

总的思路

session.get(Book.class,5); select * from t_hibernate_book where bookId=?(5) resultSet-> 5 a 10 Book book = Class.forName("com.zking.five.entity.Book"); book.setBookId(5); book.setBookName(a); book.setPrice(10);通过反射赋值 categories为什么有值 1、当前实体类的映射文件找到set标签中table属性 select * from t_hibernate_book_category 2、继续读取配置文件,拿到set标签中的key的column属性(当前类对应的表主键在桥接表中的外键) select * from t_hibernate_book_category where bid = ?(bookId=5) resultSet-> 17 5 4 18 5 2 19 5 5 3、set标签->many-to-many->配置class com.zking.five.entity.Category category.hbm.xml select * from t_hibernate_category 4、利用桥接表查询出来的数据查询关联表 select * from t_hibernate_category where category_id in(2,4,5); 2 神话 4 a0 5 a1 只会得到2,4,5 5、EntityBaseDao中的executeQuery 方法,对result进行处理,最终返回 List<Category> categories = new ArrayList<>(); while(rs.next()){ Category c = Class.forName("com.test.five.entity.Book").newInstance(); c.set.... categories.add(c) } 6、book.setCategories(Categories); 重量级框架 耗性能
转载请注明原文地址: https://www.6miu.com/read-5037948.html

最新回复(0)