第一篇:Java回顧之I/O
第二篇:Java回顧之網絡通信
第三篇:Java回顧之多線程
第四篇:Java回顧之多線程同步
第五篇:Java回顧之集合
第六篇:Java回顧之序列化
第七篇:Java回顧之反射
第八篇:Java回顧之一些基礎概念
第九篇:Java回顧之JDBC
這篇文章里,我們主要討論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的區別。