基于Java ORM框架的使用详解

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

(0)

相关推荐

  • java集合框架的体系结构详细说明

    最近在一本J2EE的书中看到了很不错的对集合框架的说明文章,筛选后发上来和大家共享,集合框架提供管理对象集合的接口和类.它包含接口,类,算法,以下是它的各个组件的说明. Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自

  • 详谈java集合框架

    1.为什么使用集合框架 当我们并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象--可以使用Java集合框架 2.Java集合框架包含的内容 接口:(父类)Collection接口下包含List(子类 )接口和Set(子类) 接口 List接口下又包含(ArrayList集合实现类和LinkedList集合实现类) Set接口下又包含(HashSet集合实现类和TreeSet集合实现类) 接口:(父类)Map接口下包含(HashMap集合实现类和TreeMap 集合实现类) *Coll

  • JavaWeb工程中集成YMP框架快速上手

    了解YMP框架 YMP于2014年10月25日正式发布1.0版本,在此之前就已在实际项目中得到广泛使用,从最初仅限团队内部使用,到合作伙伴的开发团队,再到身边的朋友,和朋友的朋友们也开始将YMP投入到实际项目中去,所以在这里我要向一直以来帮助.支持我的这些同事.朋友们表示衷心的感谢!是大家的信赖和对它的认可,才使得YMP快速成长起来,在变化过程中它一直在不断的改进.优化直至最终对外发布. 没有完美的框架,只有适合的才是好的,为了让YMP更简单易用,从2015年1月26日正在开始了v2版本的开发,

  • 关于Java集合框架面试题(含答案)上

    1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用,Java1.2提出了囊括所有集合接口.实现和算法的集合框架.在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久.它还包括在Java并发包中,阻塞接口以及它们的实现.集合框架的部分优点如下: (1)使用核心集合类降低开发成本,而非实现我们自己的集合类. (2)随着使用经过严格测试的集合框架类,代

  • 浅谈Java三大框架与应用

    前言:对于一个程序员来说,尤其是在java web端开发的程序员,三大框架:Struts+Hibernate+Spring是必须要掌握熟透的,因此,下面谈谈java三大框架的基本概念和原理. JAVA三大框架 一.Spring Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯.Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器.然而,这仅仅是

  • JavaWeb工程中集成YMP框架快速上手(二)

    本文将介绍如何在Java Web工程中集成YMP框架,操作过程基于IntelliJ IDEA做为开发环境,工程结构采用Maven构建: IntelliJ IDEA下载地址: https://www.jetbrains.com/idea/download/ Maven下载地址: http://maven.apache.org/ 创建项目 1. 打开IDEA开发环境并点击Create New Project按钮开始创建新项目向导,如下图-1所示: 2. 在New Project窗口中选中左侧Mave

  • 详解Java的Spring框架中的注解的用法

    1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: class UserManagerImpl implements UserManager { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } ... } 配置文件: <bean id="userManagerImpl" class="com.

  • java集合框架 arrayblockingqueue应用分析

    Queue ------------ 1.ArrayDeque, (数组双端队列) 2.PriorityQueue, (优先级队列) 3.ConcurrentLinkedQueue, (基于链表的并发队列) 4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQueue接口) 5.ArrayBlockingQueue, (基于数组的并发阻塞队列) 6.LinkedBlockingQueue, (基于链表的FIFO阻塞队列) 7.LinkedBlockingDeque, (

  • 基于Java ORM框架的使用详解

    ORM框架不是一个新话题,它已经流传了很多年.它的优点在于提供了概念性的.易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系.我们在这里主要关注Java中常用的两个ORM框架:Hibernate和iBatis.下面来介绍这两个框架简单的使用方法,如果将来有时间,我会深入的写一些更有意思的相关文章.HibernateHibernate是一个持久化框架和ORM框架,持久化和ORM是两个有区别的概念,持久化注重对象的存储方法是否随着程序的退出而消亡,ORM关注的是如何在数据库表和内存

  • Java MyBatis框架环境搭建详解

    目录 一.MyBatis简介 1.MyBatis历史 2.MyBatis特性 3.MyBatis下载 4.和其它持久化层技术对比 JDBC Hibernate 和 JPA MyBatis 二.搭建MyBatis 1.开发环境 2.创建maven工程 3.创建MyBatis的核心配置文件 4.创建mapper接口 5.创建MyBatis的映射文件 6.通过junit测试功能 7.加入log4j日志功能 一.MyBatis简介 1.MyBatis历史 MyBatis最初是Apache的一个开源项目i

  • Java Executor 框架的实例详解

    Java Executor 框架的实例详解 大多数并发都是通过任务执行的方式来实现的. 一般有两种方式执行任务:串行和并行. class SingleThreadWebServer { public static void main(String[] args) throws Exception { ServerSocket socket = new ServerSocket(80); while(true) { Socket conn = socket.accept(); handleRequ

  • 基于java servlet过滤器和监听器(详解)

    1 过滤器 1.过滤器是什么? servlet规范当中定义的一种特殊的组件,用于拦截容器的调用. 注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 2.如何写一个过滤器? 1.写一个java类,实现Filter接口; 2.在接口方法中实现拦截方法; 3.配置过滤器(web.xml); 3.配置初始化参数 1.配置初始化参数.(init-param) 2.通过filterconfig提供的getinitparamenter方法读取初始化的值. 4.优先级: 当有多个过

  • 基于Java中的StringTokenizer类详解(推荐)

    StringTokenizer是字符串分隔解析类型,属于:Java.util包. 1.StringTokenizer的构造函数 StringTokenizer(String str):构造一个用来解析str的StringTokenizer对象.java默认的分隔符是"空格"."制表符('\t')"."换行符('\n')"."回车符('\r')". StringTokenizer(String str,String delim)

  • 基于Java中字符串内存位置详解

    前言 之前写过一篇关于JVM内存区域划分的文章,但是昨天接到蚂蚁金服的面试,问到JVM相关的内容,解释一下JVM的内存区域划分,这部分答得还不错,但是后来又问了Java里面String存放的位置,之前只记得String是一个不变的量,应该是要存放在常量池里面的,但是后来问到new一个String出来应该是放到哪里的,这个应该是放到堆里面的,后来又问到String的引用是放在什么地方的,当时傻逼的说也是放在堆里面的,现在总结一下:基本类型的变量数据和对象的引用都是放在栈里面的,对象本身放在堆里面,

  • 基于java中集合的概念(详解)

    1.集合是储存对象的,长度可变,可以封装不同的对象 2.迭代器: 其实就是取出元素的方式(只能判断,取出,移除,无法增加) 就是把取出方式定义在集合内部,这样取出方式就可以直接访问集合内部的元素,那么取出方式就被定义成了内部类. 二每一个容器的数据结构不同,所以取出的动作细节也不一样.但是都有共性内容判断和取出,那么可以将共性提取,这些内部类都符合一个规则Iterator Iterator it = list.iterator(); while(it.hasNext()){ System.out

  • Java反射框架Reflections示例详解

    MAVEN 坐标 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.10</version> </dependency> Reflections 的作用 Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据. 获取某个类型的所有

  • Java并发框架:Executor API详解

    介绍 随着当今处理器中可用的核心数量的增加, 随着对实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行. Java 提供了自己的多线程框架,称为 Executor 框架. 1. Executor 框架是什么? Executor 框架包含一组用于有效管理工作线程的组件.Executor API 通过 Executors 将任务的执行与要执行的实际任务解耦. 这是 生产者-消费者 模式的一种实现. java.util.concurrent.Executors 提供了用于创建工作线程的线程池

  • 基于java Springboot实现教务管理系统详解

    目录 视频演示 研究背景 我国教务现状与反思 主要技术和环境: 功能截图: 总结: 视频演示 研究背景 在当今信息社会发展中中,计算机科学的飞速发展,大多数学校开始注意办公效率的发展是很关键,对学校的管理起到举足轻重的作用.基于 Internet 网络的信息服务,快速成长为现代学校中一项不可或缺的内容措施.很多校园都已经不满意商务办公管理的缓慢成长方式.学院的需求是一个功能强大的,能提供完善管理,管理信息系统的速度.社会持续向前发展,尤其是大多地方普及计算机,计算机应用已经开始向大容量的数据存储

随机推荐