这篇文章里,我们主要讨论ORM框架,以及在使用上和JDBC的区别。

  概述

  ORM框架不是一个新话题,它已经流传了很多年。它的优点在于提供了概念性的、易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系。

  我们在这里主要关注Java中常用的两个ORM框架:Hibernate和iBatis。下面来介绍这两个框架简单的使用方法,如果将来有时间,我会深入的写一些更有意思的相关文章。

  Hibernate

  Hibernate是一个持久化框架和ORM框架,持久化和ORM是两个有区别的概念,持久化注重对象的存储方法是否随着程序的退出而消亡,ORM关注的是如何在数据库表和内存对象之间建立关联。

  Hibernate使用POJO来表示Model,使用XML配置文件来配置对象和表之间的关系,它提供了一系列API来通过对对象的操作而改变数据库中的过程。

  Hibernate更强调如何对单条记录进行操作,对于更复杂的操作,它提供了一种新的面向对象的查询语言:HQL。

  我们先来定义一个关于Hibernate中Session管理的类,这里的Session类似于JDBC中的Connection。

 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对象:

 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表进行增、删、查、改的操作:

 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的定义:

 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;
}
}
 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;
}
}
 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;
}
}
 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:

 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。

  下面是测试方法:

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

Java回顾之ORM框架的更多相关文章

  1. JFinal 1.5 发布,JAVA极速WEB+ORM框架

    JFinal 爱好者一直都在问 JFinal 何时再次升级?JFinal 1.5 何时发布?以往升级都保持在每月近两次的频率,为何本次五个月过去了新版本还不出?由于作者暂时阔别码坛已有半年时间,一直无 ...

  2. Java回顾之Spring基础

    第一篇:Java回顾之I/O 第二篇:Java回顾之网络通信 第三篇:Java回顾之多线程 第四篇:Java回顾之多线程同步 第五篇:Java回顾之集合 第六篇:Java回顾之序列化 第七篇:Java ...

  3. 【C#】ORM框架

    ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁. Java典型的ORM框架有个:Hibernate,my ...

  4. 自己写ORM框架 DBUtils_DG Java(C#的写在链接里)

    ORM框架想必大家都比较熟知了,即对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同 ...

  5. 自己写ORM框架 SqlHelper_DG C#(java的写在链接里)

    ORM框架想必大家都比较熟知了,即对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同 ...

  6. 基于java注解实现自己的orm框架

    ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系. 现在常见的 ...

  7. Weed3 for java 新的微型ORM框架

    Weed3,微型ORM框架(支持:java sql,xml sql,annotation sql:存储过程:事务:缓存:监听:等...) 05年时开发了第一代: 08年时开发了第二代,那时候进入互联网 ...

  8. java集群优化——ORM框架查询优化原理

    众所周知,当下的流行的企业级架构中,ORM一直是最基础的部分,在架构设计的底层.对逻辑层提供面向对象的操作支持,而事实总是和我们预想的有所偏差,ORM在提供了较好的操作体验时,也流失了一部分原生SQL ...

  9. 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...

随机推荐

  1. Python使用logging来记录日志

    #encoding:utf-8 import logging.config from logging.handlers import RotatingFileHandler import Config ...

  2. Rochambeau---poj2912||zoj2751(并查集类似于食物链)

    题目链接:http://poj.org/problem?id=2912  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1751 ...

  3. Python开发【杂货铺】:写code经常记不住的事儿

    1.添加系统环境变量: 每次写程序,把程序路径添加到环境变量中时,总是磕磕绊绊忘一些,搞得总是从之前的程序里直接copy # 程序目录添加到系统环境变量 import os import sys im ...

  4. 使用git和gitlab进行协同开发流程

    一.基本概念 1.仓库(Repository) ①源仓库(线上版本库) 在项目的开始,项目的发起者构建起一个项目的最原始的仓库,称为origin. 源仓库的有两个作用: 1.汇总参与该项目的各个开发者 ...

  5. IIS7.5站点配置

    1. 创建站点映射目录: c:\website\release 2. 创建系统用户: a.本地用户和组-->用户-->新用户-->用户名\密码:WebUSR.xxxyyy--> ...

  6. 用SQL语句检查CPU和磁盘空间

    --查看4小时内的CPU变化值,1分钟统计一次 DECLARE @ts_now BIGINT; SELECT @ts_now = ms_ticks FROM sys.dm_os_sys_info; - ...

  7. java-信息安全(十八)java加密解密,签名等总结

    一.基本概念 加密: 密码常用术语: 明文,密文,加密,加密算法,加密秘钥,解密,解密算法,解密秘钥, 密码分析:分析密文从而推断出明文或秘钥的过程 主动攻击:入侵密码系统,采用伪造,修改,删除等手段 ...

  8. Spark SQL与Hive on Spark的比较

    简要介绍了SparkSQL与Hive on Spark的区别与联系 一.关于Spark 简介 在Hadoop的整个生态系统中,Spark和MapReduce在同一个层级,即主要解决分布式计算框架的问题 ...

  9. [py][lc]python高阶函数(匿名/map/reduce/sorted)

    匿名函数 - 传入列表 f = lambda x: x[2] print(f([1, 2, 3])) # x = [1,2,3] map使用 传入函数体 def f(x): return x*x r ...

  10. Gitlab汉化为中文版

    查看当前的gitlab版本号 cat /opt/gitlab/embedded/service/gitlab-rails/VERSION 11.1.4 打开这个网址:https://gitlab.co ...