Java回顧之ORM框架


  第一篇: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。

Hibernate的Session管理類
 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對象:

定義User對象
 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表進行增、刪、查、改的操作:

使用Hibernate對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的定義:

定義Grade對象
 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 }
定義Class對象
 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 }
定義ClassRoom對象
 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 }
定義Schedule對象
 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:

定義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。

  下面是測試方法:

iBatis測試方法
  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