hibernate关联关系(多对多)

 1. hibernate的多对多

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

 2 多对多关系注意事项

   2.1 一定要定义一个主控方
  2.2 多对多删除
    2.2.1 主控方直接删除
    2.2.2 被控方先通过主控方解除多对多关系,再删除被控方
    2.2.3 禁用级联删除
  2.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护
 

 3 hibernate自关联案列

 3.1 表信息

 t_hibernate_sys_tree_node 

3.2 实体类 TreeNode

 1 package com.yuan.four.entity;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class TreeNode {
 7     private Integer nodeId;
 8     private String nodeName;
 9     private Integer treeNodeType;
10     private Integer position;
11     private String url;
12     private TreeNode parent;
13     private Set<TreeNode> children = new HashSet<TreeNode>();
14     private Integer initChildren = 0;
15 
16     public Integer getNodeId() {
17         return nodeId;
18     }
19 
20     public void setNodeId(Integer nodeId) {
21         this.nodeId = nodeId;
22     }
23 
24     public String getNodeName() {
25         return nodeName;
26     }
27 
28     public void setNodeName(String nodeName) {
29         this.nodeName = nodeName;
30     }
31 
32     public Integer getTreeNodeType() {
33         return treeNodeType;
34     }
35 
36     public void setTreeNodeType(Integer treeNodeType) {
37         this.treeNodeType = treeNodeType;
38     }
39 
40     public Integer getPosition() {
41         return position;
42     }
43 
44     public void setPosition(Integer position) {
45         this.position = position;
46     }
47 
48     public String getUrl() {
49         return url;
50     }
51 
52     public void setUrl(String url) {
53         this.url = url;
54     }
55 
56     public TreeNode getParent() {
57         return parent;
58     }
59 
60     public void setParent(TreeNode parent) {
61         this.parent = parent;
62     }
63 
64     public Set<TreeNode> getChildren() {
65         return children;
66     }
67 
68     public void setChildren(Set<TreeNode> children) {
69         this.children = children;
70     }
71 
72     public Integer getInitChildren() {
73         return initChildren;
74     }
75 
76     public void setInitChildren(Integer initChildren) {
77         this.initChildren = initChildren;
78     }
79 
80     @Override
81     public String toString() {
82         return "TreeNode [nodeId=" + nodeId + ", nodeName=" + nodeName + ", treeNodeType=" + treeNodeType
83                 + ", position=" + position + ", url=" + url + ", parent=" + parent + ", initChildren=" + initChildren
84                 + "]";
85     }
86 
87     
88 
89     
90     
91 
92 }

 3.3 实体映射文件 TreeNode.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping>
 6     <class name="com.yuan.four.entity.TreeNode" table="t_hibernate_sys_tree_node">
 7         <id name="nodeId" type="java.lang.Integer" column="tree_node_id">
 8             <generator class="increment" />
 9         </id>
10         <property name="nodeName" type="java.lang.String"
11             column="tree_node_name">
12         </property>
13         <property name="treeNodeType" type="java.lang.Integer"
14             column="tree_node_type">
15         </property>
16         <property name="position" type="java.lang.Integer"
17             column="position">
18         </property>
19         <property name="url" type="java.lang.String"
20             column="url">
21         </property>
22         
23         <many-to-one name="parent" class="com.yuan.four.entity.TreeNode" column="parent_node_id"/>
24         
25         <set name="children" cascade="save-update" inverse="true">
26             <key column="parent_node_id"></key>
27             <one-to-many class="com.yuan.four.entity.TreeNode"/>
28         </set>
29     </class>
30 </hibernate-mapping>

3.4 将实体映射文件配置到 hibernate.cfg.xml 核心配置文件中

    一对多自关联关系

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5     <hibernate-configuration>
 6       <session-factory>
 7         <!-- 1. 数据库相关 -->
 8         <property name="connection.username">root</property>
 9         <property name="connection.password" >123</property>
10         <property name="connection.url">jdbc:mysql://localhost:3306/xm_sc?useUnicode=true&amp;characterEncoding=UTF-8
11         </property>
12         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14 
15         <!-- 配置本地事务(No CurrentSessionContext configured!) -->
16         <property name="hibernate.current_session_context_class">thread</property>
17 
18         <!-- 2. 调试相关 -->
19         <property name="show_sql">true</property>
20         <property name="format_sql">true</property>
21 
22         <!-- 3. 添加实体映射文件 -->
23         <mapping resource="com/yuan/one/entity/User.hbm.xml" />
24         <!-- 主键生成策略 -->
25         <mapping resource="com/yuan/two/Student.hbm.xml" />
26         <mapping resource="com/yuan/two/Worker.hbm.xml"/>
27         <!-- 一对多关联关系 -->
28         <mapping resource="com/yuan/three/entity/Order.hbm.xml" />
29         <mapping resource="com/yuan/three/entity/OrderItem.hbm.xml"/>
30         <!-- 一对多自关联关系 -->
31         <mapping resource="com/yuan/four/entity/TreeNode.hbm.xml"/>
32         
35 </session-factory> 36 </hibernate-configuration>

3.5  dao层  TreeNodeDao

 1 package com.yuan.four.dao;
 2 
 3 import org.hibernate.Hibernate;
 4 import org.hibernate.Session;
 5 import org.hibernate.Transaction;
 6 
 7 import com.yuan.four.entity.TreeNode;
 8 import com.yuan.two.util.SessionFactoryUtils;
 9 
10 
11 public class TreeNodeDao {
12     public TreeNode load(TreeNode treeNode) {
13         Session session = SessionFactoryUtils.openSession();
14         Transaction transaction = session.beginTransaction();
15         TreeNode t = session.load(TreeNode.class, treeNode.getNodeId());
16         if(t != null && new Integer(1).equals(treeNode.getInitChildren())) {
17             Hibernate.initialize(t.getChildren());
18             Hibernate.initialize(t.getParent());
19         }
20         transaction.commit();
21         session.close();
22         return t;
23     }
24 }

3.6  使用junit测试dao方法  TreeNodeDaoTest

 1 package com.yuan.four.dao;
 2 
 3 import org.junit.Test;
 4 
 5 import com.yuan.four.entity.TreeNode;
 6 
 7 public class TreeNodeDaoTest {
 8 
 9     private TreeNodeDao treeNodeDao = new TreeNodeDao();
10 
11 //    @Before
12 //    public void setUp() throws Exception {
13 //    }
14 //
15 //    @After
16 //    public void tearDown() throws Exception {
17 //    }
18 
19     @Test
20     public void testLoad() {
21         TreeNode treeNode = new TreeNode();
22         treeNode.setNodeId(6);
23         treeNode.setInitChildren(1);
24         
25         TreeNode t = this.treeNodeDao.load(treeNode);
26         System.out.println(t);
27         System.out.println(t.getParent());
28         System.out.println(t.getChildren());
29     }
30 
31 
32 }

 3.7 测试得到结果

TreeNode [nodeId=6, nodeName=权限管理, treeNodeType=1, position=6, url=null, parent=TreeNode [nodeId=1, nodeName=系统管理, treeNodeType=1, position=1, url=null, parent=null, initChildren=0], initChildren=0]
TreeNode [nodeId=1, nodeName=系统管理, treeNodeType=1, position=1, url=null, parent=null, initChildren=0]
[TreeNode [nodeId=10, nodeName=用户分配角色, treeNodeType=2, position=10, url=null, parent=TreeNode [nodeId=6, nodeName=权限管理, treeNodeType=1, position=6, url=null, parent=TreeNode [nodeId=1, nodeName=系统管理, treeNodeType=1, position=1, url=null, parent=null, initChildren=0], initChildren=0], initChildren=0], TreeNode [nodeId=11, nodeName=角色授予用户, treeNodeType=2, position=11, url=null, parent=TreeNode [nodeId=6, nodeName=权限管理, treeNodeType=1, position=6, url=null, parent=TreeNode [nodeId=1, nodeName=系统管理, treeNodeType=1, position=1, url=null, parent=null, initChildren=0], initChildren=0], initChildren=0]]

4. 多对多关联关系案列

4.1 表信息

 t_hibernate_book 

t_hibernate_book_category  中间表

t_hibernate_category

4.2 创建实体类 

 Book.java

 1 package com.yuan.four.entity;
 2 
 3 import java.io.Serializable;
 4 import java.util.HashSet;
 5 import java.util.Set;
 6 
 7 /**
 8  * 一对多,一本书对应多种书本类型
 9  * @author ly
10  *
11  */
12 public class Book implements Serializable{
13 //    book_id int primary key auto_increment,
14 //       book_name varchar(50) not null,
15 //       price float not null
16     private Integer bookId;
17     private String bookName;
18     private Float price;
19     
20     private Set<Category> categories = new HashSet<Category>();
21     private Integer initCategories = 0;
22 
23     public Integer getInitCategories() {
24         return initCategories;
25     }
26 
27     public void setInitCategories(Integer initCategories) {
28         this.initCategories = initCategories;
29     }
30 
31     public Integer getBookId() {
32         return bookId;
33     }
34 
35     public void setBookId(Integer bookId) {
36         this.bookId = bookId;
37     }
38 
39     public String getBookName() {
40         return bookName;
41     }
42 
43     public void setBookName(String bookName) {
44         this.bookName = bookName;
45     }
46 
47     public Float getPrice() {
48         return price;
49     }
50 
51     public void setPrice(Float price) {
52         this.price = price;
53     }
54 
55     public Set<Category> getCategories() {
56         return categories;
57     }
58 
59     public void setCategories(Set<Category> categories) {
60         this.categories = categories;
61     }
62 
63     @Override
64     public String toString() {
65         return "Book [bookId=" + bookId + ", bookName=" + bookName + ", price=" + price + "]";
66     }
67 
68     public Book(Integer bookId, String bookName) {
69         super();
70         this.bookId = bookId;
71         this.bookName = bookName;
72     }
73 
74     public Book() {
75         super();
76     }
77     
78     
79 }

 category.java

 1 package com.yuan.four.entity;
 2 
 3 import java.io.Serializable;
 4 import java.util.HashSet;
 5 import java.util.Set;
 6 
 7 /**
 8  * 一对多,一种书本类型对应多本书
 9  * @author ly
10 * 11 */ 12 public class Category implements Serializable{ 13 // category_id int primary key auto_increment, 14 // category_name varchar(50) not null 15 private Integer categoryId; 16 private String categoryName; 17 private Set<Book> books = new HashSet<Book>(); 18 public Integer getCategoryId() { 19 return categoryId; 20 } 21 public void setCategoryId(Integer categoryId) { 22 this.categoryId = categoryId; 23 } 24 public String getCategoryName() { 25 return categoryName; 26 } 27 public void setCategoryName(String categoryName) { 28 this.categoryName = categoryName; 29 } 30 public Set<Book> getBooks() { 31 return books; 32 } 33 public void setBooks(Set<Book> books) { 34 this.books = books; 35 } 36 @Override 37 public String toString() { 38 return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + "]"; 39 } 40 41 }

4.3 实体类对应的实体映射文件

  book.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping>
 6     <class name="com.yuan.four.entity.Book" table="t_hibernate_book">
 7         <cache usage="read-only" region="com.zking.five.entity.Book"/>
 8         <id name="bookId" type="java.lang.Integer" column="book_id">
 9             <generator class="increment" />
10         </id>
11         <property name="bookName" type="java.lang.String"
12             column="book_name">
13         </property>
14         <property name="price" type="java.lang.Float"
15             column="price">
16         </property>
17         
18         <!-- 
19            set标签:
20               table:对应的是中间表,没有实体类的,意味着两张主表对应的映射文件联合管理数据
21               name:当前映射文件对应的实体类对应的属性
22               cascade:级联新增修改,说白了就是当前实体类对应的表删除能否影响到关联表的数据
23               inverse:中间表的数据维护的权力交给对方
24            key标签:
25               column:当前表t_hibernate_book的主键book_id在中间表的列段bid
26            many-to-many:
27            column:代表中间表对应的除去当前表t_hibernate_book的非主键的中间表列段cid
28            class:cid对应的类
29               
30            
31          -->
32         <set table="t_hibernate_book_category" name="categories" cascade="save-update" inverse="false">
33             <!-- one -->
34             <key column="bid"></key>
35             <!-- many -->
36             <many-to-many column="cid" class="com.yuan.four.entity.Category"></many-to-many>
37         </set>
38     </class>
39 </hibernate-mapping>

 category.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping>
 6     <class name="com.yuan.four.entity.Category" table="t_hibernate_category">
 7         <id name="categoryId" type="java.lang.Integer" column="category_id">
 8             <generator class="increment" />
 9         </id>
10         <property name="categoryName" type="java.lang.String"
11             column="category_name">
12         </property>
13         
14         <set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
15             <key column="cid"></key>
16             <many-to-many column="bid" class="com.yuan.four.entity.Book"></many-to-many>
17         </set>
18     </class>
19 </hibernate-mapping>

4.4 将实体映射文件配置到hibernate.cfg.xml 中

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5     <hibernate-configuration>
 6       <session-factory>
 7         <!-- 1. 数据库相关 -->
 8         <property name="connection.username">root</property>
 9         <property name="connection.password" >123</property>
10         <property name="connection.url">jdbc:mysql://localhost:3306/xm_sc?useUnicode=true&amp;characterEncoding=UTF-8
11         </property>
12         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14 
15         <!-- 配置本地事务(No CurrentSessionContext configured!) -->
16         <property name="hibernate.current_session_context_class">thread</property>
17 
18         <!-- 2. 调试相关 -->
19         <property name="show_sql">true</property>
20         <property name="format_sql">true</property>
21 
22         <!-- 3. 添加实体映射文件 -->
23         <mapping resource="com/yuan/one/entity/User.hbm.xml" />
24         <!-- 主键生成策略 -->
25         <mapping resource="com/yuan/two/Student.hbm.xml" />
26         <mapping resource="com/yuan/two/Worker.hbm.xml"/>
27         <!-- 一对多关联关系 -->
28         <mapping resource="com/yuan/three/entity/Order.hbm.xml" />
29         <mapping resource="com/yuan/three/entity/OrderItem.hbm.xml"/>
30         <!-- 一对多自关联关系 -->
31         <mapping resource="com/yuan/four/entity/TreeNode.hbm.xml"/>
32         <!-- 多对多关联关系 -->
33         <mapping resource="com/yuan/four/entity/book.hbm.xml"/>
34         <mapping resource="com/yuan/four/entity/category.hbm.xml"/>
35       </session-factory>
36     </hibernate-configuration>

 4.5 编写dao层

  BookDao

 1 package com.yuan.four.dao;
 2 
 3 
 4 import org.hibernate.Hibernate;
 5 import org.hibernate.Session;
 6 import org.hibernate.Transaction;
 7 
 8 import com.yuan.four.entity.Book;
 9 import com.yuan.four.entity.Category;
10 import com.yuan.two.util.SessionFactoryUtils;
11 
12 
13 public class BookDao {
14     public Integer addBook(Book book) {
15         Session session = SessionFactoryUtils.openSession();
16         Transaction transaction = session.beginTransaction();
17         Integer bid = (Integer) session.save(book);
18         transaction.commit();
19         session.close();
20         return bid;
21     }
22     
23     public Integer addCategory(Category category) {
24         Session session = SessionFactoryUtils.openSession();
25         Transaction transaction = session.beginTransaction();
26         Integer cid = (Integer) session.save(category);
27         transaction.commit();
28         session.close();
29         return cid;
30     }
31     
32     public Category getCategory(Category category) {
33         Session session = SessionFactoryUtils.openSession();
34         Transaction transaction = session.beginTransaction();
35         Category c = session.get(Category.class, category.getCategoryId());
36         transaction.commit();
37         session.close();
38         return c;
39     }
40     
41     public Book getBook(Book book) {
42         Session session = SessionFactoryUtils.openSession();
43         Transaction transaction = session.beginTransaction();
44         Book b = session.get(Book.class, book.getBookId());
45         if (b != null && new Integer(1).equals(book.getInitCategories())) {
46             Hibernate.initialize(b.getCategories());
47         }
48         transaction.commit();
49         session.close();
50         return b;
51     }
52     
53     public void delBook(Book book) {
54         Session session = SessionFactoryUtils.openSession();
55         Transaction transaction = session.beginTransaction();
56         session.delete(book);
57         transaction.commit();
58         session.close();
59     }
60     
61     public void delCategory(Category category) {
62         Session session = SessionFactoryUtils.openSession();
63         Transaction transaction = session.beginTransaction();
64         Category c = session.get(Category.class, category.getCategoryId());
65         if(c!=null) {
66             for (Book b : c.getBooks()) {
67 //                通过在被控方通过主控方来解除关联关系,最后被控方再做删除
68                 b.getCategories().remove(c);
69             }
70         }
71         session.delete(c);
72         transaction.commit();
73         session.close();
74     }
75     
76     
77     
78 }

4.6 BookDao 的junit测试 BookDaoTest

 1 package com.yuan.four.dao;
 2 
 3 import org.junit.Test;
 4 
 5 import com.yuan.four.entity.Book;
 6 import com.yuan.four.entity.Category;
 7 
 8 
 9 public class BookDaoTest {
10     private BookDao bookDao = new BookDao();
11     //获取单本书籍部分信息
12     @Test
13     public void testGetBook() {
14         Book book = new Book();
15         book.setBookId(8);
16         book.setInitCategories(1);
17         Book b = this.bookDao.getBook(book );
18         System.out.println(b.getBookName());
19         System.out.println(b.getCategories());
20     }
21     
22     /**
23      * book.hbm.xml    inverse=false
24      * category.hbm.xml inverse=true
25      * 数据添加正常
26      * 书籍表、桥接表各新增一条数据
27      */
28     @Test
29     public void test1() {
30         Book book = new Book();
31         book.setBookName("yuan");
32         book.setPrice(10f);
33         Category category = new Category();
34         category.setCategoryId(5);
35 //        直接将category对象加入到新建的book中是错误的,因为此时的category是临时态的,hibernate是不会管理的
36 //        book.getCategories().add(category);
37         Category c = this.bookDao.getCategory(category);
38         
39 //        c.getBooks().add(book);
40         book.getCategories().add(c);
41         this.bookDao.addBook(book);
42     }
43 
44     /**
45      * book.hbm.xml    inverse=true
46      * category.hbm.xml inverse=true
47      * 只增加书籍表数据
48      * 桥接表不加数据
49      * 原因:双方都没有去维护关系
50      */
51     @Test
52     public void test2() {
53         Book book = new Book();
54         book.setBookName("yuan2");
55         book.setPrice(10f);
56         Category category = new Category();
57         category.setCategoryId(5);
58         Category c = this.bookDao.getCategory(category);
59         
60         book.getCategories().add(c);
61         this.bookDao.addBook(book);
62 //        c.getBooks().add(book);
63     }
64     
65     
66 }

4.7 测试结果

  注:测试时请根据测试方法上的注解进行修改

4.7.1 testGetBook() 方法测试

4.7.2 test1()测试

  t_hibernate_book表新增一条数据

  同时 t_hibernate_book_category 表新增一条数据

4.7.3 test2()测试 

 t_hibernate_book新增数据

但t_hibernate_book_category不新增数据

  

       完 !!!

原文地址:https://www.cnblogs.com/ly-0919/p/11319827.html