程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 基於Java ORM框架的使用詳解

基於Java ORM框架的使用詳解

編輯:JAVA編程入門知識
ORM框架不是一個新話題,它已經流傳了很多年。它的優點在於提供了概念性的、易於理解的數據模型,將數據庫中的表和內存中的對象建立了很好的映射關系。
我們在這裡主要關注Java中常用的兩個ORM框架:Hibernate和iBatis。下面來介紹這兩個框架簡單的使用方法,如果將來有時間,我會深入的寫一些更有意思的相關文章。
Hibernate
Hibernate是一個持久化框架和ORM框架,持久化和ORM是兩個有區別的概念,持久化注重對象的存儲方法是否隨著程序的退出而消亡,ORM關注的是如何在數據庫表和內存對象之間建立關聯。
Hibernate使用POJO來表示Model,使用XML配置文件來配置對象和表之間的關系,它提供了一系列API來通過對對象的操作而改變數據庫中的過程。
Hibernate更強調如何對單條記錄進行操作,對於更復雜的操作,它提供了一種新的面向對象的查詢語言:HQL。
我們先來定義一個關於Hibernate中Session管理的類,這裡的Session類似於JDBC中的Connection。
代碼如下:

Hibernate的Session管理類
 public class HibernateSessionManager {

     private static SessionFactory sessionFactory;

     static
     {
         try
         {
             sessionFactory = new Configuration().configure("sample/orm/hibernate/hibernate.cfg.xml").buildSessionFactory();
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
     }

     public static final ThreadLocal tl = new ThreadLocal();

     public static Session currentSession()
     {
         Session s = (Session)tl.get();
         if (s == null)
         {
             s = sessionFactory.openSession();
             tl.set(s);
         }

         return s;
     }

     public static void closeSession()
     {
         Session s = (Session)tl.get();
         tl.set(null);
         if (s != null)
         {
             s.close();
         }
     }
 }

基於單張表進行操作
下面我們來看一個簡單的示例,它沿用了<基於Java回顧之JDBC的使用詳解>中的數據庫,使用MySQL的test數據庫中的user表。
首先,我們來定義VO對象:
代碼如下:

定義User對象
 public class User implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int userID;
     private String userName;
     public void setUserID(int userID) {
         this.userID = userID;
     }
     public int getUserID() {
         return userID;
     }
     public void setUserName(String userName) {
         this.userName = userName;
     }
     public String getUserName() {
         return userName;
     }
 }

然後,我們定義User對象和數據庫中user表之間的關聯,user表中只有兩列:id和name。
代碼如下:

<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
     <class name="sample.orm.hibernate.User" table="user" catalog="test">
         <id name="userID" type="java.lang.Integer">
             <column name="id" />
             <generator class="assigned" />
         </id>
         <property name="userName" type="java.lang.String">
             <column name="name" />
         </property>
     </class>
 </hibernate-mapping>

將上述內容存儲為User.hbm.xml。
接下來,我們需要定義一個關於Hibernate的全局配置文件,這裡文件名是hibernate.cfg.xml。
代碼如下:

<?xml version='1.0' encoding='UTF-8'?>
 <!DOCTYPE hibernate-configuration PUBLIC
           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

 <hibernate-configuration>
     <session-factory>
         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
         <property name="connection.url">jdbc:mysql://localhost/test</property>
         <property name="connection.username">root</property>
         <property name="connection.password">123</property>   
         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
         <property name="show_sql">true</property>
         <property name="jdbc.fetch_size">50</property>
         <property name="jdbc.batch_size">25</property>

         <mapping resource="sample/orm/hibernate/User.hbm.xml" />       
     </session-factory>
 </hibernate-configuration>

可以看到,上述配置文件中包含了數據庫連接的信息,諸如driver信息、數據庫url、用戶名、密碼等等,還包括了我們上面定義的User.hbm.xml。
最後,我們編寫測試代碼,來對user表進行增、刪、查、改的操作:
代碼如下:

使用Hibernate對user表進行操作
 private static void getUser(int id)
 {
     Session session = HibernateSessionManager.currentSession();
     System.out.println("=====Query test=====");
     User user = (User)session.get(User.class, new Integer(id));
     if (user != null)
     {
         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());
     }
     HibernateSessionManager.closeSession();
 }

 private static void insertUser()
 {
     Session session = HibernateSessionManager.currentSession();
     System.out.println("=====Insert test=====");
     Transaction transaction = session.beginTransaction();
     User user = new User();
     user.setUserID(6);
     user.setUserName("Zhang Fei");
     session.save(user);
     session.flush();
     transaction.commit();
     HibernateSessionManager.closeSession();
     getUser(6);
 }

 private static void updateUser(int id)
 {
     Session session = HibernateSessionManager.currentSession();
     System.out.println("=====Update test=====");
     Transaction transaction = session.beginTransaction();
     User user = (User)session.get(User.class, new Integer(id));
     System.out.println("=====Before Update=====");
     if (user != null)
     {
         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());
     }
     user.setUserName("Devil");
     session.save(user);
     session.flush();
     transaction.commit();
     user = (User)session.get(User.class, new Integer(id));
     System.out.println("=====After Update=====");
     if (user != null)
     {
         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());
     }
     HibernateSessionManager.closeSession();
 }

 private static void deleteUser(int id)
 {
     Session session = HibernateSessionManager.currentSession();
     System.out.println("=====Delete test=====");
     Transaction transaction = session.beginTransaction();
     User user = (User)session.get(User.class, new Integer(id));
     System.out.println("=====Before Delte=====");
     if (user != null)
     {
         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());
     }
     session.delete(user);
     transaction.commit();
     user = (User)session.get(User.class, new Integer(id));
     System.out.println("=====After Update=====");
     if (user != null)
     {
         System.out.println("ID:" + user.getUserID() + "; Name:" + user.getUserName());
     }
     else
     {
         System.out.println("Delete successfully.");
     }
     HibernateSessionManager.closeSession();
 }

我們按照如下順序調用測試代碼:
代碼如下:

insertUser();
updateUser(6);
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對象
 package sample.orm.hibernate;

 import java.io.Serializable;
 import java.util.Set;

 public class Grade implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int gradeID;
     private String gradeName;
     private Set classes;
     public void setGradeID(int gradeID) {
         this.gradeID = gradeID;
     }
     public int getGradeID() {
         return gradeID;
     }
     public void setGradeName(String gradeName) {
         this.gradeName = gradeName;
     }
     public String getGradeName() {
         return gradeName;
     }
     public void setClasses(Set classes) {
         this.classes = classes;
     }
     public Set getClasses() {
         return classes;
     }
 }

代碼如下:

定義Class對象
 package sample.orm.hibernate;

 import java.io.Serializable;
 import java.util.Set;

 public class Class implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int classID;
     private Grade grade;
     private Set classrooms;
     private String className;
     public void setClassID(int classID) {
         this.classID = classID;
     }
     public int getClassID() {
         return classID;
     }
     public void setClassName(String className) {
         this.className = className;
     }
     public String getClassName() {
         return className;
     }
     public void setGrade(Grade grade) {
         this.grade = grade;
     }
     public Grade getGrade() {
         return grade;
     }
     public void setClassrooms(Set classrooms) {
         this.classrooms = classrooms;
     }
     public Set getClassrooms() {
         return classrooms;
     }
 }

代碼如下:

定義ClassRoom對象
 package sample.orm.hibernate;

 import java.io.Serializable;
 import java.util.Set;

 public class ClassRoom implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int classRoomID;
     private String classRoomName;
     private Set classes;
     public void setClassRoomID(int classRoomID) {
         this.classRoomID = classRoomID;
     }
     public int getClassRoomID() {
         return classRoomID;
     }
     public void setClassRoomName(String classRoomName) {
         this.classRoomName = classRoomName;
     }
     public String getClassRoomName() {
         return classRoomName;
     }
     public void setClasses(Set classes) {
         this.classes = classes;
     }
     public Set getClasses() {
         return classes;
     }
 }

代碼如下:

定義Schedule對象
 package sample.orm.hibernate;

 import java.io.Serializable;
 import java.util.Set;

 public class Schedule implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int scheduleID;
     private int classRoomID;
     private int classID;
     private Set classes;
     public void setClassRoomID(int classRoomID) {
         this.classRoomID = classRoomID;
     }
     public int getClassRoomID() {
         return classRoomID;
     }
     public void setClassID(int classID) {
         this.classID = classID;
     }
     public int getClassID() {
         return classID;
     }
     public void setClasses(Set classes) {
         this.classes = classes;
     }
     public Set getClasses() {
         return classes;
     }
     public void setScheduleID(int scheduleID) {
         this.scheduleID = scheduleID;
     }
     public int getScheduleID() {
         return scheduleID;
     }
 }

接著是各個表的關聯配置文件:
1)Grade.hbm.xml
代碼如下:

<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
     <class name="sample.orm.hibernate.Grade" table="grade" catalog="test">
         <id name="gradeID" type="java.lang.Integer">
             <column name="gradeid" />
             <generator class="assigned" />
         </id>
         <property name="gradeName" type="java.lang.String">
             <column name="gradename" />
         </property>

         <set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan">
             <key>
                 <column name="gradeid"/>
             </key>
             <one-to-many class="sample.orm.hibernate.Class"/>
         </set>
     </class>
 </hibernate-mapping>

注意上面的<set>配置,裡面的<one-to-many>節點說明了Grade和Class之間一對多的關系。
2)Class.hbm.xml
代碼如下:

<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
     <class name="sample.orm.hibernate.Class" table="class" catalog="test">
         <id name="classID" type="java.lang.Integer">
             <column name="classid" />
             <generator class="assigned" />
         </id>
         <property name="className" type="java.lang.String">
             <column name="classname" />
         </property>

         <many-to-one name="grade" class="sample.orm.hibernate.Grade" lazy="proxy" not-null="true">
             <column name="gradeid"/>
         </many-to-one>

         <set name="classrooms" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
             <key column ="classid"/>
             <many-to-many class="sample.orm.hibernate.ClassRoom" column="classroomid"/>
         </set>
     </class>
 </hibernate-mapping>

注意它定義兩個關聯:一個是和Grade之間多對一的關系,一個適合ClassRoom之間多對多的關系。
3)ClassRoom.hbm.xml
代碼如下:

<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
     <class name="sample.orm.hibernate.ClassRoom" table="classroom" catalog="test">
         <id name="classRoomID" type="java.lang.Integer">
             <column name="classroomid" />
             <generator class="assigned" />
         </id>
         <property name="classRoomName" type="java.lang.String">
             <column name="classroomname" />
         </property>

         <set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
             <key column="classroomid"/>
             <many-to-many class="sample.orm.hibernate.Class" column="classid"/>
         </set>
     </class>
 </hibernate-mapping>

它只定義了一個關聯:和Class之間的多對多關聯。
4)Schedule.hbm.xml
代碼如下:

<?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 <hibernate-mapping>
     <class name="sample.orm.hibernate.Schedule" table="schedule" catalog="test">
         <id name="scheduleID" type="java.lang.Integer">
             <column name="scheduleid" />
             <generator class="assigned" />
         </id>
         <property name="classID" type="java.lang.Integer">
             <column name="classid" />
         </property>
         <property name="classRoomID" type="java.lang.Integer">
             <column name="classroomid" />
         </property>
     </class>
 </hibernate-mapping>

這裡就不需要再定義關聯了。
我們需要在Hibernate全局配置文件中添加如下內容:
代碼如下:

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

下面是各種測試方法,在有關聯的情況下,Hibernate提供了下面幾個特性:
•延遲加載
•級聯添加
•級聯修改
•級聯刪除
代碼如下:

多表關聯情況下的一些測試方法
 private static void getClass(int gradeid)
 {
     Session session = HibernateSessionManager.currentSession();
     System.out.println("=====Get Class info=====");
     Transaction transaction = session.beginTransaction();
     Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));

     Hibernate.initialize(grade);
     Iterator iterator = grade.getClasses().iterator();
     System.out.println("年級:" + grade.getGradeName() + "包括以下班級:");
     while(iterator.hasNext())
     {
         System.out.println(grade.getGradeName() + ((Class)iterator.next()).getClassName());
     }
     HibernateSessionManager.closeSession();
 }

 private static void getSchedule(int gradeid)
 {
     Session session = HibernateSessionManager.currentSession();
     Transaction transaction = session.beginTransaction();
     Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade != null)
     {
         System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName());
     }

     Hibernate.initialize(grade.getClasses());

     Iterator iterator = grade.getClasses().iterator();
     while(iterator.hasNext())
     {
         Class c = (Class)iterator.next();
         System.out.println(grade.getGradeName() + c.getClassName() + "使用以下教室:");
         Hibernate.initialize(c.getClassrooms());
         Iterator iterator1 = c.getClassrooms().iterator();
         while(iterator1.hasNext())
         {
             System.out.println(((ClassRoom)iterator1.next()).getClassRoomName());
         }
     }
     HibernateSessionManager.closeSession();
 }

 private static void insertGrade()
 {
     Session session = HibernateSessionManager.currentSession();
     Transaction transaction = session.beginTransaction();
     Grade grade = new Grade();
     grade.setGradeID(4);
     grade.setGradeName("四年級");

     Class c1 = new Class();
     c1.setClassID(7);
     c1.setGrade(grade);
     c1.setClassName("一班");
     Class c2 = new Class();
     c2.setClassID(8);
     c2.setGrade(grade);
     c2.setClassName("二班");

     Set set = new HashSet();
     set.add(c1);
     set.add(c2);

     grade.setClasses(set);

     session.save(grade);
     session.flush();
     transaction.commit();
     HibernateSessionManager.closeSession();
     getClass(4);
 }

 private static void deleteGrade(int gradeid)
 {
     Session session = HibernateSessionManager.currentSession();
     Transaction transaction = session.beginTransaction();
     Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade != null)
     {
         session.delete(grade);
         session.flush();
     }

     transaction.commit();

     grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade == null)
     {
         System.out.println("刪除成功");
     }
     HibernateSessionManager.closeSession();
 }

 private static void updateGrade1(int gradeid)
 {
     Session session = HibernateSessionManager.currentSession();
     Transaction transaction = session.beginTransaction();
     Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade != null)
     {
         System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName());
     }
     grade.setGradeName("Grade " + gradeid);
     session.save(grade);
     session.flush();
     transaction.commit();
     HibernateSessionManager.closeSession();
     getClass(gradeid);
 }

 private static void updateGrade2(int gradeid)
 {
     Session session = HibernateSessionManager.currentSession();
     Transaction transaction = session.beginTransaction();
     Grade grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade != null)
     {
         System.out.println("ID:" + grade.getGradeID() + "; Name:" + grade.getGradeName());
     }

     Grade newGrade = new Grade();
     newGrade.setGradeID(10);
     newGrade.setGradeName(grade.getGradeName());
     Set set = grade.getClasses();
     Set newSet = new HashSet();
     Iterator iterator = set.iterator();
     while(iterator.hasNext())
     {
         Class c = (Class)iterator.next();
         Class temp = new Class();
         temp.setClassID(c.getClassID());
         temp.setClassName(c.getClassName());
         temp.setGrade(newGrade);
         newSet.add(temp);
     }
     newGrade.setClasses(newSet);
     session.delete(grade);
     session.flush();
     session.save(newGrade);
     session.flush();
     transaction.commit();
     grade = (Grade)session.get(Grade.class, new Integer(gradeid));
     if (grade == null)
     {
         System.out.println("刪除成功");
     }
     HibernateSessionManager.closeSession();
     getClass(10);
 }

按順序調用上面的方法:
代碼如下:

getClass(1);
 getSchedule(1);
 insertGrade();
 updateGrade1(4);
 updateGrade2(4);
 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對象
 package sample.orm.ibatis;

 import java.io.Serializable;

 public class User implements Serializable
 {
     private static final long serialVersionUID = 1L;
     private int userID;
     private String userName;
     public void setUserID(int userID) {
         this.userID = userID;
     }
     public int getUserID() {
         return userID;
     }
     public void setUserName(String userName) {
         this.userName = userName;
     }
     public String getUserName() {
         return userName;
     }

 }

然後需要針對這個VO,定義一個獨立的配置文件:User.xml
代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE sqlMap
     PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
     "http://www.ibatis.com/dtd/sql-map-2.dtd">

 <sqlMap namespace="User">

     <typeAlias alias="user" type="sample.orm.ibatis.User" />

    
     <cacheModel id="user-cache" type="OSCache" readOnly="true" serialize="true">
         <flushInterval milliseconds="1" />
         <flushOnExecute statement="insertUser" />
         <flushOnExecute statement="updateUser" />
         <flushOnExecute statement="getUser" />
         <flushOnExecute statement="getAllUser" />
         <property value="1" name="size" />
      </cacheModel>

     <!--
     <resultMap >
         <result property="userID" column="id" />
         <result property="userName" column="name" />
     </resultMap>
     -->

    
     <select id="getUser" parameterClass="java.lang.Integer" resultClass="user" cacheModel="user-cache" >
         select id as userID,name as userName from user where id = #userID#
     </select>
     <select id="getAllUser" resultClass="user" cacheModel="user-cache">
         select id as userID,name as userName from user
     </select>
     <update id="updateUser" parameterClass="user">
         update user SET name=#userName# WHERE id = #userID#
     </update>
     <insert id="insertUser" parameterClass="user">
         insert into user ( id, name ) VALUES ( #userID#,#userName#)
     </insert>
     <delete id="deleteUser" parameterClass="java.lang.Integer">
         delete from user where id=#userID#
     </delete>

 </sqlMap>

這個配置文件主要包括三部分:
1)緩存的配置
2)對象屬性和表字段之間的關聯
3)針對表的各種CRUD操作
然後是關於iBatis的全局配置文件SqlMapConfig.xml:
代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE sqlMapConfig
     PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
     "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

 <sqlMapConfig>

     <settings cacheModelsEnabled="true" enhancementEnabled="true"
         lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
         maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />

     <transactionManager type="JDBC">
         <dataSource type="SIMPLE">
            <property name="JDBC.Driver" value="com.mysql.jdbc.Driver" />
            <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/test" />
            <property name="JDBC.Username" value="root" />
            <property name="JDBC.Password" value="123" />
            <property name="Pool.MaximumActiveConnections" value="10" />
            <property name="Pool.MaximumIdleConnections" value="5" />
            <property name="Pool.MaximumCheckoutTime" value="120000" />
            <property name="Pool.TimeToWait" value="500" />
            <property name="Pool.PingQuery" value="select 1 from user" />
            <property name="Pool.PingEnabled" value="false" />
         </dataSource>
     </transactionManager>

     <sqlMap resource="sample/orm/ibatis/User.xml" />

 </sqlMapConfig>

和Hibernate全局配置文件類似,它也包含了數據庫連接的信息、數據庫連接池的信息以及我們定義的User.xml。
下面是測試方法:
代碼如下:

iBatis測試方法
 public class Sample {

     private SqlMapClient sqlMap = null;

     private void buildMap() throws IOException
     {
         String resource = "sample/orm/ibatis/SqlMapConfig.xml";         
         Reader reader = Resources.getResourceAsReader(resource);
         this.sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
     }

     private void insertUser() throws IOException, SQLException
     {
         System.out.println("=====Insert test=====");
         if (this.sqlMap == null)
         {
             this.buildMap();
         }
         this.sqlMap.startTransaction();
         User user = new User();
         user.setUserID(10);
         user.setUserName("Angel");

         this.sqlMap.insert("insertUser", user);
         this.sqlMap.commitTransaction();

         user = getUser(10);
         printUserInfo(user);
     }

     private void updateUser() throws IOException, SQLException, InterruptedException
     {
         System.out.println("=====Update test=====");
         if (this.sqlMap == null)
         {
             this.buildMap();
         }
         this.sqlMap.startTransaction();
         User user = new User();
         user.setUserID(10);
         user.setUserName("Devil");
         this.sqlMap.update("updateUser", user);
         this.sqlMap.commitTransaction();
         this.sqlMap.flushDataCache();
 //        Thread.sleep(3000);
         user = getUser(10);
         printUserInfo(user);
     }

     private void deleteUser() throws IOException, SQLException
     {
         System.out.println("=====Delete test=====");
         if (this.sqlMap == null)
         {
             this.buildMap();
         }
         sqlMap.flushDataCache();
         this.sqlMap.startTransaction();
         this.sqlMap.delete("deleteUser", 10);
         this.sqlMap.commitTransaction();
         getAllUser();
     }

     private User getUser(int id) throws IOException, SQLException
     {
         if (this.sqlMap == null)
         {
             this.buildMap();
         }
         User user = (User)this.sqlMap.openSession().queryForObject("getUser", id);

         return user;
     }

      private List<User> getAllUser() throws IOException, SQLException
      {
             if(this.sqlMap==null)
                this.buildMap();

          List userList=null; 
          userList=this.sqlMap.openSession().queryForList("getAllUser");
          printUserInfo(userList);
          return userList;
      }

      private void printUserInfo(User user)
      {
          System.out.println("=====user info=====");
          System.out.println("ID:" + user.getUserID() + ";Name:" + user.getUserName());
      }

      private void printUserInfo(List<User> users)
      {
          System.out.println("=====user info=====");
          for(User user:users)
          {
              System.out.println("ID:" + user.getUserID() + ";Name:" + user.getUserName());
          }
      }

      public static void main(String[] args) throws IOException, SQLException, InterruptedException
      {
          Sample sample = new Sample();
          sample.getAllUser();
          sample.insertUser();
          sample.updateUser();
          sample.deleteUser();
      }
 }

它的執行結果如下:
代碼如下:

=====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的區別。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved