(四)关联关系一对多映射

所有项目导入对应的hibernate的jar包、mysql的jar包和添加每次都需要用到的HibernateUtil.java

第一节:班级学生一对多映射实现(单向)

这里的关系是很多学生对应着一个班级,我们首先看着是单向的。

例子:

Class.java

 1 package com.wishwzp.model;
 2 
 3 public class Class {
 4 
 5     private long id;
 6     private String name;
 7     
 8     public long getId() {
 9         return id;
10     }
11     public void setId(long id) {
12         this.id = id;
13     }
14     public String getName() {
15         return name;
16     }
17     public void setName(String name) {
18         this.name = name;
19     }
20     
21     
22 }

 Class.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Class" table="t_class">
 9         <id name="id" column="classId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="className"></property>
14     </class>
15 
16 </hibernate-mapping>

Student.java

 1 package com.wishwzp.model;
 2 
 3 public class Student {
 4 
 5     private long id;
 6     private String name;
 7     private Class c;
 8     
 9     public long getId() {
10         return id;
11     }
12     public void setId(long id) {
13         this.id = id;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     
22     
23     public Class getC() {
24         return c;
25     }
26     public void setC(Class c) {
27         this.c = c;
28     }
29     @Override
30     public String toString() {
31         return "Student [id=" + id + ", name=" + name + "]";
32     }
33     
34     
35 }

Student.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Student" table="t_student">
 9         <id name="id" column="stuId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="stuName"></property>
14         
15         <!-- 学生端是多对一,也就是是多位学生对应一个班级 -->
16         <!-- 这里的name是Student.java中的getC()返回的c -->
17         <!-- 这里的column就是你映射的数据库的表的外键的的名字,就是student表的外键对class表的主键 -->
18         <!-- 这里的class就是多对一,对着那一个的表 -->
19         <many-to-one name="c" column="classId" class="com.wishwzp.model.Class"></many-to-one>
20     </class>
21 
22 </hibernate-mapping>

StudentTest.java

 1 package com.wishwzp.service;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 
 6 import com.wishwzp.model.Class;
 7 import com.wishwzp.model.Student;
 8 import com.wishwzp.util.HibernateUtil;
 9 
10 public class StudentTest {
11     
12     public static void main(String[] args) {
13         SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
14         Session session=sessionFactory.openSession(); // 生成一个session
15         session.beginTransaction(); // 开启事务
16         
17         Class c=new Class();
18         c.setName("08计本");
19         session.save(c);
20         
21         Student s1=new Student();
22         s1.setName("张三");
23         s1.setC(c);
24         
25         Student s2=new Student();
26         s2.setName("李四");
27         s2.setC(c);
28         
29         session.save(s1);
30         session.save(s2);
31        
32         session.getTransaction().commit(); // 提交事务
33         session.close(); // 关闭session
34     }
35 }

结果显示:

t_class表:

t_student表:

 第二节:Junit4 方法详解

 第(二)课的第四节我们提到过junit4,这里我们稍微将一下,首先得导入junit4的jar包

百度云:http://pan.baidu.com/s/1dFBbhhZ

密码:3z1i

setUpBeforeClass() 类初始化前调用;

tearDownAfterClass() 类初始化后调用;

setUp() 在测试方法前调用;

tearDown() 在测试方法后调用;

 例子:

创建方法:右击-new-junit Test Case

StudentTest2.java

 1 package com.wishwzp.service;
 2 
 3 import org.junit.After;
 4 import org.junit.AfterClass;
 5 import org.junit.Before;
 6 import org.junit.BeforeClass;
 7 import org.junit.Test;
 8 
 9 public class StudentTest2 {
10 
11     @BeforeClass
12     public static void setUpBeforeClass() throws Exception {
13         System.out.println("类初始化前调用...");
14     }
15 
16     @AfterClass
17     public static void tearDownAfterClass() throws Exception {
18         System.out.println("类初始化后调用...");
19     }
20 
21     @Before
22     public void setUp() throws Exception {
23         System.out.println("在测试方法前调用...");
24     }
25 
26     @After
27     public void tearDown() throws Exception {
28         System.out.println("在测试方法后调用...");
29     }
30 
31     @Test
32     public void test() {
33         System.out.println("测试方法");
34     }
35 
36 }

运行方式:右击-Run As-JUnit Test

结果显示: 

 

这里我们用“第一节:班级学生一对多映射实现(单向)”的例子来举例:

第一节:班级学生一对多映射实现(单向)例子的代码都一样不需要更改时(除主类main()除外)

StudentTest3.java

 1 package com.wishwzp.service;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import org.hibernate.Session;
 6 import org.hibernate.SessionFactory;
 7 import org.junit.After;
 8 import org.junit.AfterClass;
 9 import org.junit.Before;
10 import org.junit.BeforeClass;
11 import org.junit.Test;
12 
13 import com.wishwzp.model.Class;
14 import com.wishwzp.model.Student;
15 import com.wishwzp.util.HibernateUtil;
16 
17 public class StudentTest3 {
18 
19     private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
20     private Session session;
21     
22     @Before
23     public void setUp() throws Exception {
24         session=sessionFactory.openSession(); // 生成一个session
25         session.beginTransaction(); // 开启事务
26     }
27 
28     @After
29     public void tearDown() throws Exception {
30          session.getTransaction().commit(); // 提交事务
31          session.close(); // 关闭session
32     }
33 
34     @Test
35     public void testSaveClassAndStudent() {
36         Class c=new Class();
37         c.setName("08计本");
38         session.save(c);
39         
40         Student s1=new Student();
41         s1.setName("张三");
42         s1.setC(c);
43         
44         Student s2=new Student();
45         s2.setName("李四");
46         s2.setC(c);
47         
48         session.save(s1);
49         session.save(s2);
50     }
51 
52 }

我们发现和第一节是一样的。

 第三节:级联保存更新

 

在<many-to-one>这端,cascade 默认是”none”,假如我们希望在持久化多的一端的时候,自动级联保存和更新一的一端,我们可以把cascade 设置成”save-update”;

 例子:

第一节:班级学生一对多映射实现(单向)例子的代码都一样不需要更改时(除主类main()除外):

StudentTest4.java

 1 package com.wishwzp.service;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import org.hibernate.Session;
 6 import org.hibernate.SessionFactory;
 7 import org.junit.After;
 8 import org.junit.AfterClass;
 9 import org.junit.Before;
10 import org.junit.BeforeClass;
11 import org.junit.Test;
12 
13 import com.wishwzp.model.Class;
14 import com.wishwzp.model.Student;
15 import com.wishwzp.util.HibernateUtil;
16 
17 public class StudentTest4 {
18 
19     private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
20     private Session session;
21     
22     @Before
23     public void setUp() throws Exception {
24         session=sessionFactory.openSession(); // 生成一个session
25         session.beginTransaction(); // 开启事务
26     }
27 
28     @After
29     public void tearDown() throws Exception {
30          session.getTransaction().commit(); // 提交事务
31          session.close(); // 关闭session
32     }
33     
34     @Test
35     public void testSaveClassAndStudentWithCascade() {
36         Class c=new Class();
37         c.setName("08计本");
38         
39         Student s1=new Student();
40         s1.setName("张三");
41         s1.setC(c);
42         
43         Student s2=new Student();
44         s2.setName("李四");
45         s2.setC(c);
46         
47         session.save(s1);
48         session.save(s2);
49     }
50 
51 }

我们发现Run As-Junit Test 时会发生错误,这是因为我们需要在<many-to-one>这端,cascade 默认是”none”,我们可以把cascade 设置成”save-update”;

错误信息:

Student.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Student" table="t_student">
 9         <id name="id" column="stuId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="stuName"></property>
14         
15         <!-- 学生端是多对一,也就是是多位学生对应一个班级 -->
16         <!-- 这里的name是Student.java中的getC()返回的c -->
17         <!-- 这里的column就是你映射的数据库的表的外键的的名字,就是student表的外键对class表的主键 -->
18         <!-- 这里的class就是多对一,对着那一个的表 -->
19         <many-to-one name="c" column="classId" class="com.wishwzp.model.Class" cascade="save-update"></many-to-one>
20     </class>
21 
22 </hibernate-mapping>

我们再次运行:

结果显示:

t_class表:

t_student表:

 第四节:班级学生一对多映射实现(双向)

 例子:

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 
 6 <hibernate-configuration>
 7 
 8     <session-factory>
 9 
10         <!--数据库连接设置 -->
11         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
12         <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
13         <property name="connection.username">root</property>
14         <property name="connection.password">123456</property>
15 
16        
17         <!-- 方言 -->
18         <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
19     
20         <!-- 控制台显示SQL -->
21         <property name="show_sql">true</property>
22 
23         <!-- 自动更新表结构 -->
24         <property name="hbm2ddl.auto">update</property>
25         
26           <mapping resource="com/wishwzp/model/Student.hbm.xml"/>
27           
28           <mapping resource="com/wishwzp/model/Class.hbm.xml"/>
29           
30 
31     </session-factory>
32 
33 </hibernate-configuration>

 Class.java

 1 package com.wishwzp.model;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class Class {
 7 
 8     private long id;
 9     private String name;
10     private Set<Student> students=new HashSet<Student>();
11     
12     public long getId() {
13         return id;
14     }
15     public void setId(long id) {
16         this.id = id;
17     }
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     public Set<Student> getStudents() {
25         return students;
26     }
27     public void setStudents(Set<Student> students) {
28         this.students = students;
29     }
30     
31     
32 }

Class.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Class" table="t_class">
 9         <id name="id" column="classId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="className"></property>
14         
15         <set name="students" cascade="save-update">
16             <key column="classId"></key>
17             <one-to-many class="com.wishwzp.model.Student"/>
18         </set>
19     </class>
20 
21 </hibernate-mapping>

 Student.java

 1 package com.wishwzp.model;
 2 
 3 public class Student {
 4 
 5     private long id;
 6     private String name;
 7     private Class c;
 8     
 9     public long getId() {
10         return id;
11     }
12     public void setId(long id) {
13         this.id = id;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     
22     
23     public Class getC() {
24         return c;
25     }
26     public void setC(Class c) {
27         this.c = c;
28     }
29     @Override
30     public String toString() {
31         return "Student [id=" + id + ", name=" + name + "]";
32     }
33     
34     
35 }

Student.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Student" table="t_student">
 9         <id name="id" column="stuId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="stuName"></property>
14         
15         <many-to-one name="c" column="classId" class="com.wishwzp.model.Class" cascade="save-update"></many-to-one>
16     </class>
17 
18 </hibernate-mapping>

 StudentTest.java

 1 package com.wishwzp.service;
 2 
 3 import java.util.Iterator;
 4 import java.util.Set;
 5 
 6 import org.hibernate.Session;
 7 import org.hibernate.SessionFactory;
 8 import org.junit.After;
 9 import org.junit.Before;
10 import org.junit.Test;
11 
12 import com.wishwzp.model.Class;
13 import com.wishwzp.model.Student;
14 import com.wishwzp.util.HibernateUtil;
15 
16 public class StudentTest {
17 
18     private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
19     private Session session;
20     
21     @Before
22     public void setUp() throws Exception {
23         session=sessionFactory.openSession(); // 生成一个session
24         session.beginTransaction(); // 开启事务
25     }
26 
27     @After
28     public void tearDown() throws Exception {
29          session.getTransaction().commit(); // 提交事务
30          session.close(); // 关闭session
31     }
32 
33     @Test
34     public void testSaveClassAndStudent() {
35         Class c=new Class();
36         c.setName("08计本");
37         
38         Student s1=new Student();
39         s1.setName("张三");
40         
41         Student s2=new Student();
42         s2.setName("李四");
43         
44         c.getStudents().add(s1);
45         c.getStudents().add(s2);
46         
47         session.save(c);
48         
49     }
50     
51 }

 结果显示:

t_student表:

 

t_class表:

现在我们要测试通过班级端来查找学生端,这是我们关键的实现目的。来实现双向

StudentTest.java

 1 package com.wishwzp.service;
 2 
 3 import java.util.Iterator;
 4 import java.util.Set;
 5 
 6 import org.hibernate.Session;
 7 import org.hibernate.SessionFactory;
 8 import org.junit.After;
 9 import org.junit.Before;
10 import org.junit.Test;
11 
12 import com.wishwzp.model.Class;
13 import com.wishwzp.model.Student;
14 import com.wishwzp.util.HibernateUtil;
15 
16 public class StudentTest {
17 
18     private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
19     private Session session;
20     
21     @Before
22     public void setUp() throws Exception {
23         session=sessionFactory.openSession(); // 生成一个session
24         session.beginTransaction(); // 开启事务
25     }
26 
27     @After
28     public void tearDown() throws Exception {
29          session.getTransaction().commit(); // 提交事务
30          session.close(); // 关闭session
31     }
32 
33     
34     @Test
35     public void getStudentsByClass(){
36         Class c=(Class)session.get(Class.class, Long.valueOf(1));
37         Set<Student> students=c.getStudents();
38         Iterator it=students.iterator();
39         while(it.hasNext()){
40             Student s=(Student)it.next();
41             System.out.println(s);
42         }
43     }
44     
45 
46 }

结果显示:

我们能从一的这一端去获取多的这一端的信息;也能从一的这一端保存多的一端。这就是我们多对一的好处(这就是实现双向的好处)

 第五节:inverse 属性

 StudentTest.java

package com.wishwzp.service;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.wishwzp.model.Class;
import com.wishwzp.model.Student;
import com.wishwzp.util.HibernateUtil;

public class StudentTest {

    private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
    private Session session;
    
    @Before
    public void setUp() throws Exception {
        session=sessionFactory.openSession(); // 生成一个session
        session.beginTransaction(); // 开启事务
    }

    @After
    public void tearDown() throws Exception {
         session.getTransaction().commit(); // 提交事务
         session.close(); // 关闭session
    }
    

    @Test
    public void testAdd(){
        Class c=new Class();
        c.setName("09计本");
        
        Student s1=new Student();
        s1.setName("王五");
        
        session.save(c);
        session.save(s1);
    }

}

 结果显示:

 t_student表:

 t_class表:

 

我们发现这两个表根本没有任何关系,现在我们要将这两个表关联起来。

StudentTest.java

package com.wishwzp.service;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.wishwzp.model.Class;
import com.wishwzp.model.Student;
import com.wishwzp.util.HibernateUtil;

public class StudentTest {

    private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
    private Session session;
    
    @Before
    public void setUp() throws Exception {
        session=sessionFactory.openSession(); // 生成一个session
        session.beginTransaction(); // 开启事务
    }

    @After
    public void tearDown() throws Exception {
         session.getTransaction().commit(); // 提交事务
         session.close(); // 关闭session
    }
    

    @Test
    public void testInverse(){
        Class c=(Class)session.get(Class.class, Long.valueOf(1));
        Student s=(Student)session.get(Student.class, Long.valueOf(1));
        
        s.setC(c);//学生设置班级
        c.getStudents().add(s);//班级设置学生    
    }

}

结果显示:

我们发现这两个表有关系了。

这里我们使用inverse属性来实现一下效果:

 数据库的效果是一样的,两个数据库相关联了。

但是我们发现更新的sql语句不一样的。

 第六节:级联删除

 StudentTest.java

package com.wishwzp.service;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.wishwzp.model.Class;
import com.wishwzp.model.Student;
import com.wishwzp.util.HibernateUtil;

public class StudentTest {

    private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
    private Session session;
    
    @Before
    public void setUp() throws Exception {
        session=sessionFactory.openSession(); // 生成一个session
        session.beginTransaction(); // 开启事务
    }

    @After
    public void tearDown() throws Exception {
         session.getTransaction().commit(); // 提交事务
         session.close(); // 关闭session
    }

    @Test
    public void testDeleteClassCascade(){
        Class c=(Class)session.get(Class.class, Long.valueOf(1));
        session.delete(c);
    }
}

 这里直接运行的话就会出错的。

我们必须要改一下

Class.hbm.xml的<set>中的cascade="delete"才可以。

这样删除班级这张表的数据,学生表里面的数据也会跟着删除。

 第七节:一对多双向自身关联关系映射

 例子:

Node.java

 1 package com.wishwzp.model;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class Node {
 7 
 8     private long id;
 9     private String name;
10     
11     private Node parentNode;
12     
13     private Set<Node> childNodes=new HashSet<Node>();
14 
15     public long getId() {
16         return id;
17     }
18 
19     public void setId(long id) {
20         this.id = id;
21     }
22 
23     public String getName() {
24         return name;
25     }
26 
27     public void setName(String name) {
28         this.name = name;
29     }
30 
31     public Node getParentNode() {
32         return parentNode;
33     }
34 
35     public void setParentNode(Node parentNode) {
36         this.parentNode = parentNode;
37     }
38 
39     public Set<Node> getChildNodes() {
40         return childNodes;
41     }
42 
43     public void setChildNodes(Set<Node> childNodes) {
44         this.childNodes = childNodes;
45     }
46     
47     
48     
49 }

Node.hbm.xml

 1 <?xml version="1.0"?>
 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 
 6 <hibernate-mapping package="com.wishwzp.model">
 7 
 8     <class name="Node" table="t_node">
 9         <id name="id" column="nodeId">
10             <generator class="native"></generator>
11         </id>
12         
13         <property name="name" column="nodeName"></property>
14         
15         <many-to-one name="parentNode" column="parentId" class="com.wishwzp.model.Node" cascade="save-update"></many-to-one>
16         
17         <set name="childNodes"  inverse="true">
18             <key column="parentId"></key>
19             <one-to-many class="com.wishwzp.model.Node"/>
20         </set>
21     </class>
22 
23 </hibernate-mapping>

NodeTest.java

 1 package com.wishwzp.service;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.junit.After;
 6 import org.junit.Before;
 7 import org.junit.Test;
 8 
 9 import com.wishwzp.model.Node;
10 import com.wishwzp.util.HibernateUtil;
11 
12 public class NodeTest {
13 
14     private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
15     private Session session;
16     
17     @Before
18     public void setUp() throws Exception {
19         session=sessionFactory.openSession(); // 生成一个session
20         session.beginTransaction(); // 开启事务
21     }
22 
23     @After
24     public void tearDown() throws Exception {
25          session.getTransaction().commit(); // 提交事务
26          session.close(); // 关闭session
27     }
28 
29     @Test
30     public void testSaveMenu() {
31         Node node=new Node();
32         node.setName("根节点");
33         
34         Node subNode1=new Node();
35         subNode1.setName("子节点1");
36         
37         Node subNode2=new Node();
38         subNode2.setName("子节点2");
39         
40         subNode1.setParentNode(node);
41         subNode2.setParentNode(node);
42         
43         session.save(subNode1);
44         session.save(subNode2);
45     }
46     
47     
48 }

结果显示:

我们发现根节点是老大,已经没有上面的节点了,二子节点1和子节点2它们分别有根节点的。

原文地址:https://www.cnblogs.com/wishwzp/p/5481215.html