第三次作业随想篇:Hibernate之多对多篇

Hibernate值多对多篇:

首先Hibernate基于数据库持久层框架,好的OR框架。封装了JDBC对数据库繁琐的操作,完全以面向对象的方式来操作数据库,提供了以及一级,二级缓存。

下面就来谈谈Hibernate的优点与缺点:

  优点:

    1.对jdbc访问数据库进行了封装,简化了繁琐的操作。

    2.映射的灵活性

    3.非侵入性,移植性好。(就是说只需将你的映射文件及其配置文件移植到相应另一台计算机上照样可以运行,因为表的它是自己检查创建的,这一点非常好,不像Mybatis那样,你要去建一个和他的映射文件字段,属性一样的表,才能运行,这一点比Mybatis好)

    4.提供一级二级缓存。

  缺点:

    1.无法对SQL进行优化。

    2.配置复杂。(什么一对一,一对多,多对多),这里主要针对自己手写,不过用工具根据数据库表生成实体类和映射文件就十分简单了。

    3.SQL执行效率低。

    4.不支持批量的删除,修改。

今天先来说说它的多对多:

  这里举的例子为学生与课程的关系,一个学生可以选修多个课程,一个课程可被多个学生选择,标准的多对多关系。

配置文件如下:主要用于指明数据库连接的信息及其是否展示SQL,方言,检查更新,关联相应的映射文件。

  

 1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8 <session-factory>
 9 
10     <property name="connection.username">scott</property>
11     <property name="connection.password">orcl</property>
12 
13     <property name="connection.url">
14         jdbc:mysql://localhost:3306/dbs
15     </property>
16     <!-- 
17         作用:根据持久化类和映射文件生成表
18         validate   在启动的时候验证持久化类和表的描述是否一样
19         create-drop 一般不用,当hibernate启动的时候生成表,结束的时候删除表
20         create  只要启动Hibernate的时候生成表
21         update 在启动时候检查持久文件和表是否对应对应则不该,不对应则新建
22     -->
23     <property name="hbm2ddl.auto">update</property>
24     <!-- 
25         显示hibernate内部生成的sql语句
26     -->
27     <property name="show_sql">true</property>
28     <property name="dialect">
29         org.hibernate.dialect.MySQLDialect
30     </property>
31     <!-- 如果映射文件有两个要注意 -->
32     <mapping resource="cn/hp/relaDemo/Students.hbm.xml" />
33     <mapping resource="cn/hp/relaDemo/Course.hbm.xml" />
34 </session-factory>
35 
36 </hibernate-configuration>
View Code
 相应的Course映射文件:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 
 5 <hibernate-mapping>
 6   
 7   <class name="cn.hp.relaDemo.Course">
 8   
 9     <id name="cid" type="java.lang.Long" length="5">
10       <generator class="increment"></generator>
11     </id>
12     
13      <property name="cname" length="10" type="java.lang.String"></property>
14          
15      <property name="cdepartment" length="10" type="java.lang.String"></property>
16      
17      <set name="students" table="student_course" cascade="save-update">
18        <key>
19          <column name="cid"></column>
20        </key>
21        <many-to-many class="cn.hp.relaDemo.Students"></many-to-many>
22      </set>
23      
24   </class>
25 </hibernate-mapping>
26   
View Code
相应的Student映射文件:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 
 5 <hibernate-mapping>
 6   
 7   <class name="cn.hp.relaDemo.Students">
 8   <!-- name -->
 9     <id name="sid" type="java.lang.Long" length="5">
10     <!-- 主键的产生 -->
11       <generator class="increment"></generator>
12     </id>
13     
14      <property name="sname" length="10" type="java.lang.String"></property>
15          
16      <property name="description" length="10" type="java.lang.String"></property>
17      
18      <!-- 多对一 的关系
19           column指明外键
20           table是用来描述第三张表的。
21      -->
22      <set name="course" table="student_course" cascade="save-update">
23        <key>
24           <column name="sid"></column>
25        </key>
26        <!-- class指明它所指向的多对多的类,column指明此表的外键 -->
27        <many-to-many class="cn.hp.relaDemo.Course" column="cid">
28        </many-to-many>
29      </set>
30      
31   </class>
32 </hibernate-mapping>
33   
View Code

   相应的实体类

 1 package cn.hp.relaDemo;
 2 
 3 import java.io.Serializable;
 4 import java.util.Set;
 5 
 6 public class Course implements Serializable{
 7 /**
 8      * 
 9      */
10     private static final long serialVersionUID = 1L;
11     //注意加的不是外键,若加的是外键则不是面向对象思想
12     private long cid;
13     private String cname;
14     private String cdepartment;
15     private Set<Students> students;
16     
17     public long getCid() {
18         return cid;
19     }
20     public void setCid(long cid) {
21         this.cid = cid;
22     }
23     public String getCname() {
24         return cname;
25     }
26     public void setCname(String cname) {
27         this.cname = cname;
28     }
29     public String getCdepartment() {
30         return cdepartment;
31     }
32     public void setCdepartment(String cdepartment) {
33         this.cdepartment = cdepartment;
34     }
35     public Set<Students> getStudents() {
36         return students;
37     }
38     public void setStudents(Set<Students> students) {
39         this.students = students;
40     }
41     
42 }
View Code
 1 package cn.hp.relaDemo;
 2 
 3 import java.io.Serializable;
 4 import java.util.Set;
 5 
 6 public class Students implements Serializable{
 7     
 8     private Long sid;
 9     private String sname;
10     private String description;
11     private Set<Course> course;
12     
13     public Long getSid() {
14         return sid;
15     }
16     public void setSid(Long sid) {
17         this.sid = sid;
18     }
19     public String getSname() {
20         return sname;
21     }
22     public void setSname(String sname) {
23         this.sname = sname;
24     }
25     public String getDescription() {
26         return description;
27     }
28     public void setDescription(String description) {
29         this.description = description;
30     }
31     public Set<Course> getCourse() {
32         return course;
33     }
34     public void setCourse(Set<Course> course) {
35         this.course = course;
36     }
37 
38 
39 }
View Code

   用于加载配置文件及其创建SessionFactory的帮助类:

 1 package cn.hp.test;
 2 
 3 import org.hibernate.SessionFactory;
 4 import org.hibernate.cfg.Configuration;
 5 import org.junit.Before;
 6 
 7 public class Hibernateabs {
 8     protected static SessionFactory sessionFactory=null;
 9     //子类和父类同时有static语句块,先执行父类的语句块
10     static String url=null;
11 /*    static
12     {
13         //准备加载相应的配置文件
14                 Configuration configuration=new Configuration();
15                 //加载Hibernate的配置文件
16                 configuration.configure();
17                 //SessionFactory是一个
18                 sessionFactory=configuration.buildSessionFactory();
19                 //打开数据库的连接准备就绪数据库的操作,查询不需开启事物
20     }*/
21     @Before
22      public void before()
23         {
24             //准备加载相应的配置文件
25             Configuration configuration=new Configuration();
26             //加载Hibernate的配置文件
27             configuration.configure(url);
28             //SessionFactory是一个
29             sessionFactory=configuration.buildSessionFactory();
30             //打开数据库的连接准备就绪数据库的操作,查询不需开启事物
31         }
32 }
View Code

  接下来是相应的各种测试包括级联保存,查找,删除,修改,等等。

  1 package cn.hp.test;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashSet;
  5 import java.util.List;
  6 import java.util.Set;
  7 
  8 import org.hibernate.Session;
  9 import org.hibernate.Transaction;
 10 import org.junit.Test;
 11 
 12 import cn.hp.relaDemo.Course;
 13 import cn.hp.relaDemo.Students;
 14 
 15 /*
 16  * 1.新建一个课程
 17  * 2.新建一个学生
 18  * 3.新建课程的同时新建学生
 19  * 4.已经存在一个学生,新建一个课程,建立课程和学生之间的联系
 20  * 5.已经存在一个课程,新建一个学生,建立关联
 21  * 6.已经存在一个课程,已经存在一个学生,建立关联
 22  * 7.把已经存在的学生加入到已经存在的课程中
 23  * 8.把一个学生加入到一些课程中
 24  * 9.把多个学生加入到多个课程中
 25  * 10.把一个已经存在的学生从一个已经存在的课程中移除
 26  * 11.把一些已经存在的学生从一个已经存在的课程中移除
 27  * 12.把一个学生从一个课程转到另一个课程
 28  * 13.删除课程
 29  * 14.删除学生
 30  */
 31 public class ManyToManyTest extends Hibernateabs{
 32     
 33     static{
 34         url="cn/hp/relaDemo/hibernate.cfg.xml";
 35     }
 36     @Test
 37     public void test1()
 38     {
 39         Session session=sessionFactory.openSession();
 40         Transaction transaction=session.beginTransaction();
 41         
 42         Students students=new Students();
 43         students.setDescription("desc33");
 44         students.setSname("hepanhen");
 45         
 46         Course course=new Course();
 47         course.setCname("niybi");
 48         course.setCname("xoaoniu");
 49         
 50         Set<Course>courses=new HashSet<Course>();
 51         courses.add(course);
 52         
 53         students.setCourse(courses);
 54         session.save(students);
 55         transaction.commit();
 56         session.close();
 57     }
 58     
 59     /*
 60      * 已经存在一个课程,新建一个学生,建立关联
 61      * 从学生角度出发
 62      */
 63     @Test
 64     public void test2()
 65     {
 66         Session session=sessionFactory.openSession();
 67         Transaction transaction=session.beginTransaction();
 68         
 69         Students students=new Students();
 70         students.setDescription("鸟人");
 71         students.setSname("name");
 72         
 73         //先得到学生
 74         Course course=(Course) session.get(Course.class, 1L);
 75         
 76         Set<Course> courses=new HashSet<Course>();
 77         courses.add(course);
 78         students.setCourse(courses);
 79         
 80         session.save(students);
 81         transaction.commit();
 82         session.close();
 83     }
 84     
 85     /*
 86      * 已经存在一个课程,已经存在一个学生,建立关联
 87      * 从学生端出发,也可以从课程端出发
 88      */
 89     @Test
 90     public void test3()
 91     {
 92         Session session=sessionFactory.openSession();
 93         Transaction transaction=session.beginTransaction();
 94         
 95         Course course=(Course) session.get(Course.class, 2L);
 96         Students students=(Students) session.get(Students.class, 3L);
 97         
 98         students.getCourse().add(course);
 99         
100         transaction.commit();
101         session.close();
102     }
103     
104     /*
105      * 把多个学生加入到一个课程中,注意效率的问题
106      */
107     @Test
108     public void test4()
109     {
110         Session session=sessionFactory.openSession();
111         Transaction transaction=session.beginTransaction();
112         
113         Students student4=(Students) session.get(Students.class, 4L);
114         Students student5=(Students) session.get(Students.class, 5L);
115         Course course=(Course) session.get(Course.class, 3L);
116         course.getStudents().add(student5);
117         //又取一次是不会发出Sql语句,course.getStudents(),性能的优化问题。
118         course.getStudents().add(student4);
119         
120         transaction.commit();
121         session.close();
122     }
123     
124     /*
125      * 把一个学生加入到一些课程中,从学生端出发比较简单
126      */
127     @Test
128     public void test5()
129     {
130         Session session=sessionFactory.openSession();
131         Transaction transaction=session.beginTransaction();
132         
133         Students student4=(Students) session.get(Students.class, 4L);
134         List <Course> course=session.createQuery("from Course where cid= 1 or cid =2 or cid=3").list();
135         //又取一次是不会发出Sql语句,course.getStudents(),性能的优化问题。
136         for(int i=0;i<course.size();i++)
137         {
138             student4.getCourse().add(course.get(i));
139         }
140         
141         transaction.commit();
142         session.close();
143     }
144     
145     /*
146      * 把学生从一个课程转移到另一个课程,从学生端维护关系
147      * 第一种方法,直接使用Set的方法
148      */
149     @Test
150     public void test6()
151     {
152         Session session=sessionFactory.openSession();
153         Transaction transaction=session.beginTransaction();
154         
155         Students student4=(Students) session.get(Students.class, 2L);
156         Course course=(Course) session.get(Course.class, 3L);
157         //新建一个set集合用于添加数据
158         Set<Course> courses=new HashSet<Course>();
159         courses.add(course);
160         
161         student4.setCourse(courses);
162         
163         transaction.commit();
164         session.close();
165     }
166     
167     /*
168      * 把学生从一个课程转移到另一个课程,从学生端维护关系
169      * 第二种方法,采用先添加后移除的方法
170      */
171     @Test
172     public void test7()
173     {
174         Session session=sessionFactory.openSession();
175         Transaction transaction=session.beginTransaction();
176         
177         Students student4=(Students) session.get(Students.class, 2L);
178         Course course3=(Course) session.get(Course.class, 3L);
179         Course course4=(Course) session.get(Course.class, 4L);
180         student4.getCourse().remove(course3);
181         student4.getCourse().add(course4);
182         
183         transaction.commit();
184         session.close();
185     }
186     
187     /*
188      * 将选修课程一的所有学生删除,删除之前需要先解除关系
189      */
190     @Test
191     public void test8()
192     {
193         Session session=sessionFactory.openSession();
194         Transaction transaction=session.beginTransaction();
195         
196         Course course3=(Course) session.get(Course.class, 1L);
197         //org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): 
198         //出现错误,删除学生之前需要先解除关系
199         Set<Students> students=course3.getStudents();
200         
201         for(Students stu:students)
202         {
203             course3.setStudents(null);//先解除关系/**/
204             session.delete(stu);
205         }
206         
207         transaction.commit();
208         session.close();
209     }
210     
211 }
View Code

  测试数据库是否连接成功的单元测试类。

 1 package cn.hp.test;
 2 
 3 import org.junit.Test;
 4 
 5 public class CreatTable extends Hibernateabs{
 6 
 7     static{
 8         url="cn/hp/relaDemo/hibernate.cfg.xml";
 9     }
10     @Test
11     public void testcreate()
12     {
13         System.out.println("shujuku succeed...");
14     }
15     
16 }
View Code

  连接成功打印出

      

运行第一个单元测试用例:控制台输出:

 

显示数据插入插入成功:

打开数据库,果然相应的数据已经插入数据库

 

 

 

其他的单元测试用例自己去测吧。

 

注意:

  这里要注意级联和维护外键的问题。

  若要通过保存学生级联保存他所选的课程,就需要,设置相应的cascade="save-update"属性,若果你没有设置级联保存,他就告诉你没有没法保存。

  错误信息如下:

  

 

posted @ 2016-03-20 01:33  2013551631何攀  阅读(135)  评论(0编辑  收藏  举报