所有项目导入对应的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它们分别有根节点的。