Java回顾之ORM框架


这篇文章里,我们主要讨论ORM框架,以及在使用上和JDBC的区别。

  概述

  ORM框架不是一个新话题,它已经流传了很多年。它的优点在于提供了概念性的、易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系。

  我们在这里主要关注Java中常用的两个ORM框架:Hibernate和iBatis。下面来介绍这两个框架简单的使用方法,如果将来有时间,我会深入的写一些更有意思的相关文章。

  Hibernate

  Hibernate是一个持久化框架和ORM框架,持久化和ORM是两个有区别的概念,持久化注重对象的存储方法是否随着程序的退出而消亡,ORM关注的是如何在数据库表和内存对象之间建立关联。

  Hibernate使用POJO来表示Model,使用XML配置文件来配置对象和表之间的关系,它提供了一系列API来通过对对象的操作而改变数据库中的过程。

  Hibernate更强调如何对单条记录进行操作,对于更复杂的操作,它提供了一种新的面向对象的查询语言:HQL。

  我们先来定义一个关于Hibernate中Session管理的类,这里的Session类似于JDBC中的Connection。

复制代码
 1 public class HibernateSessionManager {  2 
 3     private static SessionFactory sessionFactory;  4     
 5     static
 6  {  7         try
 8  {  9             sessionFactory = new Configuration().configure("sample/orm/hibernate/hibernate.cfg.xml").buildSessionFactory(); 10  } 11         catch(Exception ex) 12  { 13  ex.printStackTrace(); 14  } 15  } 16     
17     public static final ThreadLocal tl = new ThreadLocal(); 18     
19     public static Session currentSession() 20  { 21         Session s = (Session)tl.get(); 22         if (s == null) 23  { 24             s = sessionFactory.openSession(); 25  tl.set(s); 26  } 27         
28         return s; 29  } 30     
31     public static void closeSession() 32  { 33         Session s = (Session)tl.get(); 34         tl.set(null); 35         if (s != null) 36  { 37  s.close(); 38  } 39  } 40 }
复制代码

  基于单张表进行操作

  下面我们来看一个简单的示例,它沿用了Java回顾之JDBC中的数据库,使用MySQL的test数据库中的user表。

  首先,我们来定义VO对象:

复制代码
 1 public class User implements Serializable  2 {  3     private static final long serialVersionUID = 1L;  4     private int userID;  5     private String userName;  6     public void setUserID(int userID) {  7         this.userID = userID;  8  }  9     public int getUserID() { 10         return userID; 11  } 12     public void setUserName(String userName) { 13         this.userName = userName; 14  } 15     public String getUserName() { 16         return userName; 17  } 18 }
复制代码

  然后,我们定义User对象和数据库中user表之间的关联,user表中只有两列:id和name。

复制代码
 1 <?xml version="1.0"?>
 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     <class name="sample.orm.hibernate.User" table="user" catalog="test">
 7         <id name="userID" type="java.lang.Integer">
 8             <column name="id" />
 9             <generator class="assigned" />
10         </id>
11         <property name="userName" type="java.lang.String">
12             <column name="name" />
13         </property>
14     </class>
15 </hibernate-mapping>
复制代码

  将上述内容存储为User.hbm.xml。

  接下来,我们需要定义一个关于Hibernate的全局配置文件,这里文件名是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://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7     <session-factory>
 8         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 9         <property name="connection.url">jdbc:mysql://localhost/test</property>
10         <property name="connection.username">root</property>
11         <property name="connection.password">123</property>    
12         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
13         <property name="show_sql">true</property>
14         <property name="jdbc.fetch_size">50</property>
15         <property name="jdbc.batch_size">25</property>
16         
17         <mapping resource="sample/orm/hibernate/User.hbm.xml" />        
18     </session-factory>
19 </hibernate-configuration>
复制代码

  可以看到,上述配置文件中包含了数据库连接的信息,诸如driver信息、数据库url、用户名、密码等等,还包括了我们上面定义的User.hbm.xml。

  最后,我们编写测试代码,来对user表进行增、删、查、改的操作:

复制代码
 1 private static void getUser(int id)  2 {  3     Session session = HibernateSessionManager.currentSession();  4     System.out.println("=====Query test=====");  5     User user = (User)session.get(User.class, new Integer(id));  6     if (user != null)  7  {  8         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());  9  } 10  HibernateSessionManager.closeSession(); 11 } 12 
13 private static void insertUser() 14 { 15     Session session = HibernateSessionManager.currentSession(); 16     System.out.println("=====Insert test====="); 17     Transaction transaction = session.beginTransaction(); 18     User user = new User(); 19     user.setUserID(6); 20     user.setUserName("Zhang Fei"); 21  session.save(user); 22  session.flush(); 23  transaction.commit(); 24  HibernateSessionManager.closeSession(); 25     getUser(6); 26 } 27 
28 private static void updateUser(int id) 29 { 30     Session session = HibernateSessionManager.currentSession(); 31     System.out.println("=====Update test====="); 32     Transaction transaction = session.beginTransaction(); 33     User user = (User)session.get(User.class, new Integer(id)); 34     System.out.println("=====Before Update====="); 35     if (user != null) 36  { 37         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName()); 38  } 39     user.setUserName("Devil"); 40  session.save(user); 41  session.flush(); 42  transaction.commit(); 43     user = (User)session.get(User.class, new Integer(id)); 44     System.out.println("=====After Update====="); 45     if (user != null) 46  { 47         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName()); 48  } 49  HibernateSessionManager.closeSession(); 50 } 51 
52 private static void deleteUser(int id) 53 { 54     Session session = HibernateSessionManager.currentSession(); 55     System.out.println("=====Delete test====="); 56     Transaction transaction = session.beginTransaction(); 57     User user = (User)session.get(User.class, new Integer(id)); 58     System.out.println("=====Before Delte====="); 59     if (user != null) 60  { 61         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName()); 62  } 63  session.delete(user); 64  transaction.commit(); 65     user = (User)session.get(User.class, new Integer(id)); 66     System.out.println("=====After Update====="); 67     if (user != null) 68  { 69         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName()); 70  } 71     else
72  { 73         System.out.println("Delete successfully."); 74  } 75  HibernateSessionManager.closeSession(); 76 }
复制代码

  我们按照如下顺序调用测试代码:

1 insertUser(); 2 updateUser(6); 3 deleteUser(6);

  可以看到如下结果:

复制代码
=====Insert test===== Hibernate: insert into test.user (name, id) values (?, ?) =====Query test===== Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=? ID:6; Name:Zhang Fei =====Update test===== Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====Before Update===== ID:6; Name:Zhang Fei Hibernate: update test.user set name=? where id=?
=====After Update===== ID:6; Name:Devil =====Delete test===== Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====Before Delte===== ID:6; Name:Devil Hibernate: delete from test.user where id=? Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====After Delete===== Delete successfully.
复制代码

  请注意,上面的结果中,输出了每次数据库操作时的SQL语句,这是因为在配置文件中有如下配置:

<property name="show_sql">true</property>

  我们可以在开发调试阶段将其打开,在部署到客户方时,将其关闭。

  基于多表关联的操作

  Hibernate在建立多表关联时,根据主外键的设置,表之间的关联可以分为三种:一对一、一对多和多对多。这些关联会体现在表的配置文件以及VO中。

  下面我们来看一个经典的多表关联示例:排课表。数据库中建立如下四张表:Grade/Class/ClassRoom/Schedule。刚发现,使用MySQL自带的管理器导出表定义基本是一件不可能的任务。。。。

  上述各表除ID以及必要外键外,只有Name一列。

  然后看各个VO的定义:

复制代码
 1 package sample.orm.hibernate;  2 
 3 import java.io.Serializable;  4 import java.util.Set;  5 
 6 public class Grade implements Serializable  7 {  8     private static final long serialVersionUID = 1L;  9     private int gradeID; 10     private String gradeName; 11     private Set classes; 12     public void setGradeID(int gradeID) { 13         this.gradeID = gradeID; 14  } 15     public int getGradeID() { 16         return gradeID; 17  } 18     public void setGradeName(String gradeName) { 19         this.gradeName = gradeName; 20  } 21     public String getGradeName() { 22         return gradeName; 23  } 24     public void setClasses(Set classes) { 25         this.classes = classes; 26  } 27     public Set getClasses() { 28         return classes; 29  } 30 }
复制代码
复制代码
 1 package sample.orm.hibernate;  2 
 3 import java.io.Serializable;  4 import java.util.Set;  5 
 6 public class Class implements Serializable  7 {  8     private static final long serialVersionUID = 1L;  9     private int classID; 10     private Grade grade; 11     private Set classrooms; 12     private String className; 13     public void setClassID(int classID) { 14         this.classID = classID; 15  } 16     public int getClassID() { 17         return classID; 18  } 19     public void setClassName(String className) { 20         this.className = className; 21  } 22     public String getClassName() { 23         return className; 24  } 25     public void setGrade(Grade grade) { 26         this.grade = grade; 27  } 28     public Grade getGrade() { 29         return grade; 30  } 31     public void setClassrooms(Set classrooms) { 32         this.classrooms = classrooms; 33  } 34     public Set getClassrooms() { 35         return classrooms; 36  } 37 }
复制代码
复制代码
 1 package sample.orm.hibernate;  2 
 3 import java.io.Serializable;  4 import java.util.Set;  5 
 6 public class ClassRoom implements Serializable  7 {  8     private static final long serialVersionUID = 1L;  9     private int classRoomID; 10     private String classRoomName; 11     private Set classes; 12     public void setClassRoomID(int classRoomID) { 13         this.classRoomID = classRoomID; 14  } 15     public int getClassRoomID() { 16         return classRoomID; 17  } 18     public void setClassRoomName(String classRoomName) { 19         this.classRoomName = classRoomName; 20  } 21     public String getClassRoomName() { 22         return classRoomName; 23  } 24     public void setClasses(Set classes) { 25         this.classes = classes; 26  } 27     public Set getClasses() { 28         return classes; 29  } 30 }
复制代码
复制代码
 1 package sample.orm.hibernate;  2 
 3 import java.io.Serializable;  4 import java.util.Set;  5 
 6 public class Schedule implements Serializable  7 {  8     private static final long serialVersionUID = 1L;  9     private int scheduleID; 10     private int classRoomID; 11     private int classID; 12     private Set classes; 13     public void setClassRoomID(int classRoomID) { 14         this.classRoomID = classRoomID; 15  } 16     public int getClassRoomID() { 17         return classRoomID; 18  } 19     public void setClassID(int classID) { 20         this.classID = classID; 21  } 22     public int getClassID() { 23         return classID; 24  } 25     public void setClasses(Set classes) { 26         this.classes = classes; 27  } 28     public Set getClasses() { 29         return classes; 30  } 31     public void setScheduleID(int scheduleID) { 32         this.scheduleID = scheduleID; 33  } 34     public int getScheduleID() { 35         return scheduleID; 36  } 37 }
复制代码

  接着是各个表的关联配置文件:

  1)Grade.hbm.xml

复制代码
 1 <?xml version="1.0"?>
 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     <class name="sample.orm.hibernate.Grade" table="grade" catalog="test">
 7         <id name="gradeID" type="java.lang.Integer">
 8             <column name="gradeid" />
 9             <generator class="assigned" />
10         </id>
11         <property name="gradeName" type="java.lang.String">
12             <column name="gradename" />
13         </property>
14         
15         <set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan">
16             <key>
17                 <column name="gradeid"/>
18             </key>
19             <one-to-many class="sample.orm.hibernate.Class"/>
20         </set>
21     </class>
22 </hibernate-mapping>
复制代码

  注意上面的<set>配置,里面的<one-to-many>节点说明了Grade和Class之间一对多的关系。

  2)Class.hbm.xml

复制代码
 1 <?xml version="1.0"?>
 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     <class name="sample.orm.hibernate.Class" table="class" catalog="test">
 7         <id name="classID" type="java.lang.Integer">
 8             <column name="classid" />
 9             <generator class="assigned" />
10         </id>
11         <property name="className" type="java.lang.String">
12             <column name="classname" />
13         </property>
14         
15         <many-to-one name="grade" class="sample.orm.hibernate.Grade" lazy="proxy" not-null="true">
16             <column name="gradeid"/>
17         </many-to-one>
18         
19         <set name="classrooms" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
20             <key column ="classid"/>
21             <many-to-many class="sample.orm.hibernate.ClassRoom" column="classroomid"/>
22         </set>
23     </class>
24 </hibernate-mapping>
复制代码

  注意它定义两个关联:一个是和Grade之间多对一的关系,一个适合ClassRoom之间多对多的关系。

  3)ClassRoom.hbm.xml

复制代码
 1 <?xml version="1.0"?>
 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     <class name="sample.orm.hibernate.ClassRoom" table="classroom" catalog="test">
 7         <id name="classRoomID" type="java.lang.Integer">
 8             <column name="classroomid" />
 9             <generator class="assigned" />
10         </id>
11         <property name="classRoomName" type="java.lang.String">
12             <column name="classroomname" />
13         </property>
14         
15         <set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
16             <key column="classroomid"/>
17             <many-to-many class="sample.orm.hibernate.Class" column="classid"/>
18         </set>
19     </class>
20 </hibernate-mapping>
复制代码

  它只定义了一个关联:和Class之间的多对多关联。

  4)Schedule.hbm.xml

复制代码
 1 <?xml version="1.0"?>
 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     <class name="sample.orm.hibernate.Schedule" table="schedule" catalog="test">
 7         <id name="scheduleID" type="java.lang.Integer">
 8             <column name="scheduleid" />
 9             <generator class="assigned" />
10         </id>
11         <property name="classID" type="java.lang.Integer">
12             <column name="classid" />
13         </property>
14         <property name="classRoomID" type="java.lang.Integer">
15             <column name="classroomid" />
16         </property>
17     </class>
18 </hibernate-mapping>
复制代码

  这里就不需要再定义关联了。

  我们需要在Hibernate全局配置文件中添加如下内容:

1 <mapping resource="sample/orm/hibernate/Grade.hbm.xml" />
2 <mapping resource="sample/orm/hibernate/Class.hbm.xml" />
3 <mapping resource="sample/orm/hibernate/ClassRoom.hbm.xml" />
4 <mapping resource="sample/orm/hibernate/Schedule.hbm.xml" />

  下面是各种测试方法,在有关联的情况下,Hibernate提供了下面几个特性:

  • 延迟加载
  • 级联添加
  • 级联修改
  • 级联删除
复制代码
 1 private static void getClass(int gradeid)  2 {  3  Session session = HibernateSessionManager.currentSession();  4  System.out.println("=====Get Class info=====");  5  Transaction transaction = session.beginTransaction();  6  Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));  7     
 8  Hibernate.initialize(grade);  9  Iterator iterator = grade.getClasses().iterator();  10  System.out.println("年级:" + grade.getGradeName() + "包括以下班级:");  11  while(iterator.hasNext())  12  {  13  System.out.println(grade.getGradeName() + ((Class)iterator.next()).getClassName());  14  }  15  HibernateSessionManager.closeSession();  16 }  17 
 18 private static void getSchedule(int gradeid)  19 {  20  Session session = HibernateSessionManager.currentSession();  21  Transaction transaction = session.beginTransaction();  22  Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));  23  if (grade != null)  24  {  25  System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName());  26  }  27     
 28  Hibernate.initialize(grade.getClasses());  29     
 30  Iterator iterator = grade.getClasses().iterator();  31  while(iterator.hasNext())  32  {  33  Class c = (Class)iterator.next();  34  System.out.println(grade.getGradeName() + c.getClassName() + "使用以下教室:");  35  Hibernate.initialize(c.getClassrooms());  36  Iterator iterator1 = c.getClassrooms().iterator();  37  while(iterator1.hasNext())  38  {  39  System.out.println(((ClassRoom)iterator1.next()).getClassRoomName());  40  }  41  }  42  HibernateSessionManager.closeSession();  43 }  44 
 45 private static void insertGrade()  46 {  47  Session session = HibernateSessionManager.currentSession();  48  Transaction transaction = session.beginTransaction();  49  Grade grade = new Grade();  50  grade.setGradeID(4);  51  grade.setGradeName("四年级");  52     
 53  Class c1 = new Class();  54  c1.setClassID(7);  55  c1.setGrade(grade);  56  c1.setClassName("一班");  57  Class c2 = new Class();  58  c2.setClassID(8);  59  c2.setGrade(grade);  60  c2.setClassName("二班");  61     
 62  Set set = new HashSet();  63  set.add(c1);  64  set.add(c2);  65     
 66  grade.setClasses(set);  67     
 68  session.save(grade);  69  session.flush();  70  transaction.commit();  71  HibernateSessionManager.closeSession();  72  getClass(4);  73 }  74 
 75 private static void deleteGrade(int gradeid)  76 {  77  Session session = HibernateSessionManager.currentSession();  78  Transaction transaction = session.beginTransaction();  79  Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));  80  if (grade != null)  81  {  82  session.delete(grade);  83  session.flush();  84  }  85     
 86  transaction.commit();  87     
 88  grade = (Grade)session.get(Grade.class, new Integer(gradeid));  89  if (grade == null)  90  {  91  System.out.println("删除成功");  92  }  93  HibernateSessionManager.closeSession();  94 }  95 
 96 private static void updateGrade1(int gradeid)  97 {  98  Session session = HibernateSessionManager.currentSession();  99  Transaction transaction = session.beginTransaction(); 100  Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid)); 101  if (grade != null) 102  { 103  System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName()); 104  } 105  grade.setGradeName("Grade " + gradeid); 106  session.save(grade); 107  session.flush(); 108  transaction.commit(); 109  HibernateSessionManager.closeSession(); 110  getClass(gradeid); 111 } 112 
113 private static void updateGrade2(int gradeid) 114 { 115  Session session = HibernateSessionManager.currentSession(); 116  Transaction transaction = session.beginTransaction(); 117  Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid)); 118  if (grade != null) 119  { 120  System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName()); 121  } 122     
123  Grade newGrade = new Grade(); 124  newGrade.setGradeID(10); 125  newGrade.setGradeName(grade.getGradeName()); 126  Set set = grade.getClasses(); 127  Set newSet = new HashSet(); 128  Iterator iterator = set.iterator(); 129  while(iterator.hasNext()) 130  { 131  Class c = (Class)iterator.next(); 132  Class temp = new Class(); 133  temp.setClassID(c.getClassID()); 134  temp.setClassName(c.getClassName()); 135  temp.setGrade(newGrade); 136  newSet.add(temp); 137  } 138  newGrade.setClasses(newSet); 139  session.delete(grade); 140  session.flush(); 141  session.save(newGrade); 142  session.flush(); 143  transaction.commit(); 144  grade = (Grade)session.get(Grade.class, new Integer(gradeid)); 145  if (grade == null) 146  { 147  System.out.println("删除成功"); 148  } 149  HibernateSessionManager.closeSession(); 150  getClass(10); 151 }
复制代码

  按顺序调用上面的方法:

复制代码
1 getClass(1); 2 getSchedule(1); 3 insertGrade(); 4 updateGrade1(4); 5 updateGrade2(4); 6 deleteGrade(10);
复制代码

  执行结果如下:

复制代码
=====Get Class info=====
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:一年级包括以下班级:
一年级二班
一年级一班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
ID:1; Name:一年级
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
一年级一班使用以下教室:
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
教室二
教室五
教室一
一年级二班使用以下教室:
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
教室四
教室二
教室六
Hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
Hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
Hibernate: insert into test.grade (gradename, gradeid) values (?, ?)
Hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
Hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
=====Get Class info=====
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:四年级包括以下班级:
四年级二班
四年级一班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
ID:4; Name:四年级
Hibernate: update test.grade set gradename=? where gradeid=?
=====Get Class info=====
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:Grade 4包括以下班级:
Grade 4二班
Grade 4一班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
ID:4; Name:Grade 4
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
Hibernate: delete from test.class where classid=?
Hibernate: delete from test.class where classid=?
Hibernate: delete from test.grade where gradeid=?
Hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
Hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
Hibernate: insert into test.grade (gradename, gradeid) values (?, ?)
Hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
Hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
删除成功
=====Get Class info=====
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:Grade 4包括以下班级:
Grade 4一班
Grade 4二班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
Hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
Hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
Hibernate: delete from test.class where classid=?
Hibernate: delete from test.class where classid=?
Hibernate: delete from test.grade where gradeid=?
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
删除成功
复制代码

  同样,执行结果中包含了各个SQL语句。

  iBatis

  iBatis是另外一种ORM框架,和Hibernate擅长操作单条记录不同,iBatis是基于SQL模板的,可以说,iBatis每次和数据库进行操作时,都有明确的SQL语句,而这些SQL语句,就是我们定义在配置文件中的。

  我们还是以test数据库中的user表为例,简单说明iBatis的操作流程:

  首先,我们还是需要定义VO对象,这里还是使用和Hibernate讲解时相同的User:

复制代码
 1 package sample.orm.ibatis;  2 
 3 import java.io.Serializable;  4 
 5 public class User implements Serializable  6 {  7  private static final long serialVersionUID = 1L;  8  private int userID;  9  private String userName; 10  public void setUserID(int userID) { 11  this.userID = userID; 12  } 13  public int getUserID() { 14  return userID; 15  } 16  public void setUserName(String userName) { 17  this.userName = userName; 18  } 19  public String getUserName() { 20  return userName; 21  } 22     
23 }
复制代码

  然后需要针对这个VO,定义一个独立的配置文件:User.xml

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE sqlMap  3  PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"  4  "http://www.ibatis.com/dtd/sql-map-2.dtd">
 5     
 6 <sqlMap namespace="User">
 7 
 8     <typeAlias alias="user" type="sample.orm.ibatis.User" />
 9     
10     
11     <cacheModel id="user-cache" type="OSCache" readOnly="true" serialize="true">
12         <flushInterval milliseconds="1" />
13         <flushOnExecute statement="insertUser" />
14         <flushOnExecute statement="updateUser" />
15         <flushOnExecute statement="getUser" />
16         <flushOnExecute statement="getAllUser" />
17         <property value="1" name="size" />
18      </cacheModel>
19     
20     <!--
21  <resultMap > 22  <result property="userID" column="id" /> 23  <result property="userName" column="name" /> 24  </resultMap> 25     -->
26     
27     
28     <select id="getUser" parameterClass="java.lang.Integer" resultClass="user" cacheModel="user-cache" >
29  select id as userID,name as userName from user where id = #userID# 30     </select>
31     <select id="getAllUser" resultClass="user" cacheModel="user-cache">
32  select id as userID,name as userName from user 33     </select>
34     <update id="updateUser" parameterClass="user">
35  update user SET name=#userName# WHERE id = #userID# 36     </update>
37     <insert id="insertUser" parameterClass="user">
38  insert into user ( id, name ) VALUES ( #userID#,#userName#) 39     </insert>
40     <delete id="deleteUser" parameterClass="java.lang.Integer">
41  delete from user where id=#userID# 42     </delete>
43     
44 </sqlMap>
复制代码

  这个配置文件主要包括三部分:

  1)缓存的配置

  2)对象属性和表字段之间的关联

  3)针对表的各种CRUD操作

  然后是关于iBatis的全局配置文件SqlMapConfig.xml:

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE sqlMapConfig  3  PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"  4  "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
 5     
 6 <sqlMapConfig>
 7 
 8     <settings cacheModelsEnabled="true" enhancementEnabled="true"
 9  lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
10  maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
11         
12     <transactionManager type="JDBC">
13         <dataSource type="SIMPLE">
14            <property name="JDBC.Driver" value="com.mysql.jdbc.Driver" />
15            <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/test" />
16            <property name="JDBC.Username" value="root" />
17            <property name="JDBC.Password" value="123" />
18            <property name="Pool.MaximumActiveConnections" value="10" />
19            <property name="Pool.MaximumIdleConnections" value="5" />
20            <property name="Pool.MaximumCheckoutTime" value="120000" />
21            <property name="Pool.TimeToWait" value="500" />
22            <property name="Pool.PingQuery" value="select 1 from user" />
23            <property name="Pool.PingEnabled" value="false" />
24         </dataSource>
25     </transactionManager>
26     
27     <sqlMap resource="sample/orm/ibatis/User.xml" />
28 
29 </sqlMapConfig>
复制代码

  和Hibernate全局配置文件类似,它也包含了数据库连接的信息、数据库连接池的信息以及我们定义的User.xml。

  下面是测试方法:

复制代码
 1 public class Sample {  2 
 3     private SqlMapClient sqlMap = null;  4     
 5     private void buildMap() throws IOException  6  {  7         String resource = "sample/orm/ibatis/SqlMapConfig.xml";  8         Reader reader = Resources.getResourceAsReader(resource);  9         this.sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);  10  }  11     
 12     private void insertUser() throws IOException, SQLException  13  {  14         System.out.println("=====Insert test=====");  15         if (this.sqlMap == null)  16  {  17             this.buildMap();  18  }  19         this.sqlMap.startTransaction();  20         User user = new User();  21         user.setUserID(10);  22         user.setUserName("Angel");  23         
 24         this.sqlMap.insert("insertUser", user);  25         this.sqlMap.commitTransaction();  26         
 27         user = getUser(10);  28  printUserInfo(user);  29  }  30     
 31     private void updateUser() throws IOException, SQLException, InterruptedException  32  {  33         System.out.println("=====Update test=====");  34         if (this.sqlMap == null)  35  {  36             this.buildMap();  37  }  38         this.sqlMap.startTransaction();  39         User user = new User();  40         user.setUserID(10);  41         user.setUserName("Devil");  42         this.sqlMap.update("updateUser", user);  43         this.sqlMap.commitTransaction();  44         this.sqlMap.flushDataCache();  45 // Thread.sleep(3000);
 46         user = getUser(10);  47  printUserInfo(user);  48  }  49     
 50     private void deleteUser() throws IOException, SQLException  51  {  52         System.out.println("=====Delete test=====");  53         if (this.sqlMap == null)  54  {  55             this.buildMap();  56  }  57  sqlMap.flushDataCache();  58         this.sqlMap.startTransaction();  59         this.sqlMap.delete("deleteUser", 10);  60         this.sqlMap.commitTransaction();  61  getAllUser();  62  }  63     
 64     private User getUser(int id) throws IOException, SQLException  65  {  66         if (this.sqlMap == null)  67  {  68             this.buildMap();  69  }  70         User user = (User)this.sqlMap.openSession().queryForObject("getUser", id);  71         
 72         return user;  73  }  74 
 75      private List<User> getAllUser() throws IOException, SQLException  76  {  77             if(this.sqlMap==null)  78                this.buildMap();  79          
 80          List userList=null;  81          userList=this.sqlMap.openSession().queryForList("getAllUser");  82  printUserInfo(userList);  83          return userList;  84  }  85      
 86      private void printUserInfo(User user)  87  {  88          System.out.println("=====user info=====");  89          System.out.println("ID:" + user.getUserID() + ";Name:" + user.getUserName());  90  }  91      
 92      private void printUserInfo(List<User> users)  93  {  94          System.out.println("=====user info=====");  95          for(User user:users)  96  {  97              System.out.println("ID:" + user.getUserID() + ";Name:" + user.getUserName());  98  }  99  } 100      
101      public static void main(String[] args) throws IOException, SQLException, InterruptedException 102  { 103          Sample sample = new Sample(); 104  sample.getAllUser(); 105  sample.insertUser(); 106  sample.updateUser(); 107  sample.deleteUser(); 108  } 109 }
复制代码

  它的执行结果如下:

复制代码
=====user info===== ID:1;Name:Zhang San ID:2;Name:TEST =====Insert test=====
=====user info===== ID:10;Name:Angel =====Update test=====
=====user info===== ID:10;Name:Devil =====Delete test=====
=====user info===== ID:1;Name:Zhang San ID:2;Name:TEST
复制代码

  这篇文章只是简单介绍了Hibernate和iBatis的用法,并没有涉及全部,例如Hibernate的事务、拦截、HQL、iBatis的缓存等等。这里主要是为了描述ORM框架的基本轮廓,以及在使用方式上它和JDBC的区别。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM