• 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的区别。

  • 相关阅读:
    vue中@事件处理函数的柯里化
    一个例子生动理解js的原型_js的原型prototype和__protopy__区别
    vue3自定义v-model
    js初始化一个特定值的array
    dom的clientHeight、scrollHeight以及offsetHeight
    ts踩坑记录
    常见问题1
    资料share
    几种开放源码的TCPIP协议栈
    阻塞与非阻塞,同步与异步
  • 原文地址:https://www.cnblogs.com/wing011203/p/3075467.html
Copyright © 2020-2023  润新知