基于Java ORM框架的使用详解
程序员文章站
2023-12-17 08:46:16
orm框架不是一个新话题,它已经流传了很多年。它的优点在于提供了概念性的、易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系。我们在这里主要关注java中...
orm框架不是一个新话题,它已经流传了很多年。它的优点在于提供了概念性的、易于理解的数据模型,将数据库中的表和内存中的对象建立了很好的映射关系。
我们在这里主要关注java中常用的两个orm框架:hibernate和ibatis。下面来介绍这两个框架简单的使用方法,如果将来有时间,我会深入的写一些更有意思的相关文章。
hibernate
hibernate是一个持久化框架和orm框架,持久化和orm是两个有区别的概念,持久化注重对象的存储方法是否随着程序的退出而消亡,orm关注的是如何在数据库表和内存对象之间建立关联。
hibernate使用pojo来表示model,使用xml配置文件来配置对象和表之间的关系,它提供了一系列api来通过对对象的操作而改变数据库中的过程。
hibernate更强调如何对单条记录进行操作,对于更复杂的操作,它提供了一种新的面向对象的查询语言:hql。
我们先来定义一个关于hibernate中session管理的类,这里的session类似于jdbc中的connection。
hibernate的session管理类
public class hibernatesessionmanager {
private static sessionfactory sessionfactory;
static
{
try
{
sessionfactory = new configuration().configure("sample/orm/hibernate/hibernate.cfg.xml").buildsessionfactory();
}
catch(exception ex)
{
ex.printstacktrace();
}
}
public static final threadlocal tl = new threadlocal();
public static session currentsession()
{
session s = (session)tl.get();
if (s == null)
{
s = sessionfactory.opensession();
tl.set(s);
}
return s;
}
public static void closesession()
{
session s = (session)tl.get();
tl.set(null);
if (s != null)
{
s.close();
}
}
}
基于单张表进行操作
下面我们来看一个简单的示例,它沿用了<基于java回顾之jdbc的使用详解>中的数据库,使用mysql的test数据库中的user表。
首先,我们来定义vo对象:
定义user对象
public class user implements serializable
{
private static final long serialversionuid = 1l;
private int userid;
private string username;
public void setuserid(int userid) {
this.userid = userid;
}
public int getuserid() {
return userid;
}
public void setusername(string username) {
this.username = username;
}
public string getusername() {
return username;
}
}
然后,我们定义user对象和数据库中user表之间的关联,user表中只有两列:id和name。
<?xml version="1.0"?>
<!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="sample.orm.hibernate.user" table="user" catalog="test">
<id name="userid" type="java.lang.integer">
<column name="id" />
<generator class="assigned" />
</id>
<property name="username" type="java.lang.string">
<column name="name" />
</property>
</class>
</hibernate-mapping>
将上述内容存储为user.hbm.xml。
接下来,我们需要定义一个关于hibernate的全局配置文件,这里文件名是hibernate.cfg.xml。
<?xml version='1.0' encoding='utf-8'?>
<!doctype hibernate-configuration public
"-//hibernate/hibernate configuration dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">root</property>
<property name="connection.password">123</property>
<property name="dialect">org.hibernate.dialect.mysqldialect</property>
<property name="show_sql">true</property>
<property name="jdbc.fetch_size">50</property>
<property name="jdbc.batch_size">25</property>
<mapping resource="sample/orm/hibernate/user.hbm.xml" />
</session-factory>
</hibernate-configuration>
可以看到,上述配置文件中包含了数据库连接的信息,诸如driver信息、数据库url、用户名、密码等等,还包括了我们上面定义的user.hbm.xml。
最后,我们编写测试代码,来对user表进行增、删、查、改的操作:
使用hibernate对user表进行操作
private static void getuser(int id)
{
session session = hibernatesessionmanager.currentsession();
system.out.println("=====query test=====");
user user = (user)session.get(user.class, new integer(id));
if (user != null)
{
system.out.println("id:" + user.getuserid() + "; name:" + user.getusername());
}
hibernatesessionmanager.closesession();
}
private static void insertuser()
{
session session = hibernatesessionmanager.currentsession();
system.out.println("=====insert test=====");
transaction transaction = session.begintransaction();
user user = new user();
user.setuserid(6);
user.setusername("zhang fei");
session.save(user);
session.flush();
transaction.commit();
hibernatesessionmanager.closesession();
getuser(6);
}
private static void updateuser(int id)
{
session session = hibernatesessionmanager.currentsession();
system.out.println("=====update test=====");
transaction transaction = session.begintransaction();
user user = (user)session.get(user.class, new integer(id));
system.out.println("=====before update=====");
if (user != null)
{
system.out.println("id:" + user.getuserid() + "; name:" + user.getusername());
}
user.setusername("devil");
session.save(user);
session.flush();
transaction.commit();
user = (user)session.get(user.class, new integer(id));
system.out.println("=====after update=====");
if (user != null)
{
system.out.println("id:" + user.getuserid() + "; name:" + user.getusername());
}
hibernatesessionmanager.closesession();
}
private static void deleteuser(int id)
{
session session = hibernatesessionmanager.currentsession();
system.out.println("=====delete test=====");
transaction transaction = session.begintransaction();
user user = (user)session.get(user.class, new integer(id));
system.out.println("=====before delte=====");
if (user != null)
{
system.out.println("id:" + user.getuserid() + "; name:" + user.getusername());
}
session.delete(user);
transaction.commit();
user = (user)session.get(user.class, new integer(id));
system.out.println("=====after update=====");
if (user != null)
{
system.out.println("id:" + user.getuserid() + "; name:" + user.getusername());
}
else
{
system.out.println("delete successfully.");
}
hibernatesessionmanager.closesession();
}
我们按照如下顺序调用测试代码:
insertuser();
updateuser(6);
deleteuser(6);
可以看到如下结果:
=====insert test=====
hibernate: insert into test.user (name, id) values (?, ?)
=====query test=====
hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
id:6; name:zhang fei
=====update test=====
hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====before update=====
id:6; name:zhang fei
hibernate: update test.user set name=? where id=?
=====after update=====
id:6; name:devil
=====delete test=====
hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====before delte=====
id:6; name:devil
hibernate: delete from test.user where id=?
hibernate: select user0_.id as id0_, user0_.name as name0_0_ from test.user user0_ where user0_.id=?
=====after delete=====
delete successfully.
请注意,上面的结果中,输出了每次数据库操作时的sql语句,这是因为在配置文件中有如下配置:
<property name="show_sql">true</property>
我们可以在开发调试阶段将其打开,在部署到客户方时,将其关闭。
基于多表关联的操作
hibernate在建立多表关联时,根据主外键的设置,表之间的关联可以分为三种:一对一、一对多和多对多。这些关联会体现在表的配置文件以及vo中。
下面我们来看一个经典的多表关联示例:排课表。数据库中建立如下四张表:grade/class/classroom/schedule。刚发现,使用mysql自带的管理器导出表定义基本是一件不可能的任务。。。。
上述各表除id以及必要外键外,只有name一列。
然后看各个vo的定义:
定义grade对象
package sample.orm.hibernate;
import java.io.serializable;
import java.util.set;
public class grade implements serializable
{
private static final long serialversionuid = 1l;
private int gradeid;
private string gradename;
private set classes;
public void setgradeid(int gradeid) {
this.gradeid = gradeid;
}
public int getgradeid() {
return gradeid;
}
public void setgradename(string gradename) {
this.gradename = gradename;
}
public string getgradename() {
return gradename;
}
public void setclasses(set classes) {
this.classes = classes;
}
public set getclasses() {
return classes;
}
}
定义class对象
package sample.orm.hibernate;
import java.io.serializable;
import java.util.set;
public class class implements serializable
{
private static final long serialversionuid = 1l;
private int classid;
private grade grade;
private set classrooms;
private string classname;
public void setclassid(int classid) {
this.classid = classid;
}
public int getclassid() {
return classid;
}
public void setclassname(string classname) {
this.classname = classname;
}
public string getclassname() {
return classname;
}
public void setgrade(grade grade) {
this.grade = grade;
}
public grade getgrade() {
return grade;
}
public void setclassrooms(set classrooms) {
this.classrooms = classrooms;
}
public set getclassrooms() {
return classrooms;
}
}
定义classroom对象
package sample.orm.hibernate;
import java.io.serializable;
import java.util.set;
public class classroom implements serializable
{
private static final long serialversionuid = 1l;
private int classroomid;
private string classroomname;
private set classes;
public void setclassroomid(int classroomid) {
this.classroomid = classroomid;
}
public int getclassroomid() {
return classroomid;
}
public void setclassroomname(string classroomname) {
this.classroomname = classroomname;
}
public string getclassroomname() {
return classroomname;
}
public void setclasses(set classes) {
this.classes = classes;
}
public set getclasses() {
return classes;
}
}
定义schedule对象
package sample.orm.hibernate;
import java.io.serializable;
import java.util.set;
public class schedule implements serializable
{
private static final long serialversionuid = 1l;
private int scheduleid;
private int classroomid;
private int classid;
private set classes;
public void setclassroomid(int classroomid) {
this.classroomid = classroomid;
}
public int getclassroomid() {
return classroomid;
}
public void setclassid(int classid) {
this.classid = classid;
}
public int getclassid() {
return classid;
}
public void setclasses(set classes) {
this.classes = classes;
}
public set getclasses() {
return classes;
}
public void setscheduleid(int scheduleid) {
this.scheduleid = scheduleid;
}
public int getscheduleid() {
return scheduleid;
}
}
接着是各个表的关联配置文件:
1)grade.hbm.xml
<?xml version="1.0"?>
<!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="sample.orm.hibernate.grade" table="grade" catalog="test">
<id name="gradeid" type="java.lang.integer">
<column name="gradeid" />
<generator class="assigned" />
</id>
<property name="gradename" type="java.lang.string">
<column name="gradename" />
</property>
<set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan">
<key>
<column name="gradeid"/>
</key>
<one-to-many class="sample.orm.hibernate.class"/>
</set>
</class>
</hibernate-mapping>
注意上面的<set>配置,里面的<one-to-many>节点说明了grade和class之间一对多的关系。
2)class.hbm.xml
<?xml version="1.0"?>
<!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="sample.orm.hibernate.class" table="class" catalog="test">
<id name="classid" type="java.lang.integer">
<column name="classid" />
<generator class="assigned" />
</id>
<property name="classname" type="java.lang.string">
<column name="classname" />
</property>
<many-to-one name="grade" class="sample.orm.hibernate.grade" lazy="proxy" not-null="true">
<column name="gradeid"/>
</many-to-one>
<set name="classrooms" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
<key column ="classid"/>
<many-to-many class="sample.orm.hibernate.classroom" column="classroomid"/>
</set>
</class>
</hibernate-mapping>
注意它定义两个关联:一个是和grade之间多对一的关系,一个适合classroom之间多对多的关系。
3)classroom.hbm.xml
<?xml version="1.0"?>
<!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="sample.orm.hibernate.classroom" table="classroom" catalog="test">
<id name="classroomid" type="java.lang.integer">
<column name="classroomid" />
<generator class="assigned" />
</id>
<property name="classroomname" type="java.lang.string">
<column name="classroomname" />
</property>
<set name="classes" lazy="true" inverse="true" cascade="all-delete-orphan" table="schedule">
<key column="classroomid"/>
<many-to-many class="sample.orm.hibernate.class" column="classid"/>
</set>
</class>
</hibernate-mapping>
它只定义了一个关联:和class之间的多对多关联。
4)schedule.hbm.xml
<?xml version="1.0"?>
<!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd 3.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="sample.orm.hibernate.schedule" table="schedule" catalog="test">
<id name="scheduleid" type="java.lang.integer">
<column name="scheduleid" />
<generator class="assigned" />
</id>
<property name="classid" type="java.lang.integer">
<column name="classid" />
</property>
<property name="classroomid" type="java.lang.integer">
<column name="classroomid" />
</property>
</class>
</hibernate-mapping>
这里就不需要再定义关联了。
我们需要在hibernate全局配置文件中添加如下内容:
<mapping resource="sample/orm/hibernate/grade.hbm.xml" />
<mapping resource="sample/orm/hibernate/class.hbm.xml" />
<mapping resource="sample/orm/hibernate/classroom.hbm.xml" />
<mapping resource="sample/orm/hibernate/schedule.hbm.xml" />
下面是各种测试方法,在有关联的情况下,hibernate提供了下面几个特性:
•延迟加载
•级联添加
•级联修改
•级联删除
多表关联情况下的一些测试方法
private static void getclass(int gradeid)
{
session session = hibernatesessionmanager.currentsession();
system.out.println("=====get class info=====");
transaction transaction = session.begintransaction();
grade grade = (grade)session.get(grade.class, new integer(gradeid));
hibernate.initialize(grade);
iterator iterator = grade.getclasses().iterator();
system.out.println("年级:" + grade.getgradename() + "包括以下班级:");
while(iterator.hasnext())
{
system.out.println(grade.getgradename() + ((class)iterator.next()).getclassname());
}
hibernatesessionmanager.closesession();
}
private static void getschedule(int gradeid)
{
session session = hibernatesessionmanager.currentsession();
transaction transaction = session.begintransaction();
grade grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade != null)
{
system.out.println("id:" + grade.getgradeid() + "; name:" + grade.getgradename());
}
hibernate.initialize(grade.getclasses());
iterator iterator = grade.getclasses().iterator();
while(iterator.hasnext())
{
class c = (class)iterator.next();
system.out.println(grade.getgradename() + c.getclassname() + "使用以下教室:");
hibernate.initialize(c.getclassrooms());
iterator iterator1 = c.getclassrooms().iterator();
while(iterator1.hasnext())
{
system.out.println(((classroom)iterator1.next()).getclassroomname());
}
}
hibernatesessionmanager.closesession();
}
private static void insertgrade()
{
session session = hibernatesessionmanager.currentsession();
transaction transaction = session.begintransaction();
grade grade = new grade();
grade.setgradeid(4);
grade.setgradename("四年级");
class c1 = new class();
c1.setclassid(7);
c1.setgrade(grade);
c1.setclassname("一班");
class c2 = new class();
c2.setclassid(8);
c2.setgrade(grade);
c2.setclassname("二班");
set set = new hashset();
set.add(c1);
set.add(c2);
grade.setclasses(set);
session.save(grade);
session.flush();
transaction.commit();
hibernatesessionmanager.closesession();
getclass(4);
}
private static void deletegrade(int gradeid)
{
session session = hibernatesessionmanager.currentsession();
transaction transaction = session.begintransaction();
grade grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade != null)
{
session.delete(grade);
session.flush();
}
transaction.commit();
grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade == null)
{
system.out.println("删除成功");
}
hibernatesessionmanager.closesession();
}
private static void updategrade1(int gradeid)
{
session session = hibernatesessionmanager.currentsession();
transaction transaction = session.begintransaction();
grade grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade != null)
{
system.out.println("id:" + grade.getgradeid() + "; name:" + grade.getgradename());
}
grade.setgradename("grade " + gradeid);
session.save(grade);
session.flush();
transaction.commit();
hibernatesessionmanager.closesession();
getclass(gradeid);
}
private static void updategrade2(int gradeid)
{
session session = hibernatesessionmanager.currentsession();
transaction transaction = session.begintransaction();
grade grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade != null)
{
system.out.println("id:" + grade.getgradeid() + "; name:" + grade.getgradename());
}
grade newgrade = new grade();
newgrade.setgradeid(10);
newgrade.setgradename(grade.getgradename());
set set = grade.getclasses();
set newset = new hashset();
iterator iterator = set.iterator();
while(iterator.hasnext())
{
class c = (class)iterator.next();
class temp = new class();
temp.setclassid(c.getclassid());
temp.setclassname(c.getclassname());
temp.setgrade(newgrade);
newset.add(temp);
}
newgrade.setclasses(newset);
session.delete(grade);
session.flush();
session.save(newgrade);
session.flush();
transaction.commit();
grade = (grade)session.get(grade.class, new integer(gradeid));
if (grade == null)
{
system.out.println("删除成功");
}
hibernatesessionmanager.closesession();
getclass(10);
}
按顺序调用上面的方法:
getclass(1);
getschedule(1);
insertgrade();
updategrade1(4);
updategrade2(4);
deletegrade(10);
执行结果如下:
=====get class info=====
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:一年级包括以下班级:
一年级二班
一年级一班
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
id:1; name:一年级
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
一年级一班使用以下教室:
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
教室二
教室五
教室一
一年级二班使用以下教室:
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
教室四
教室二
教室六
hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
hibernate: insert into test.grade (gradename, gradeid) values (?, ?)
hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
=====get class info=====
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:四年级包括以下班级:
四年级二班
四年级一班
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
id:4; name:四年级
hibernate: update test.grade set gradename=? where gradeid=?
=====get class info=====
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:grade 4包括以下班级:
grade 4二班
grade 4一班
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
id:4; name:grade 4
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
hibernate: delete from test.class where classid=?
hibernate: delete from test.class where classid=?
hibernate: delete from test.grade where gradeid=?
hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
hibernate: select class_.classid, class_.classname as classname2_, class_.gradeid as gradeid2_ from test.class class_ where class_.classid=?
hibernate: insert into test.grade (gradename, gradeid) values (?, ?)
hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
hibernate: insert into test.class (classname, gradeid, classid) values (?, ?, ?)
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
删除成功
=====get class info=====
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
年级:grade 4包括以下班级:
grade 4一班
grade 4二班
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
hibernate: select classes0_.gradeid as gradeid1_, classes0_.classid as classid1_, classes0_.classid as classid0_, classes0_.classname as classname2_0_, classes0_.gradeid as gradeid2_0_ from test.class classes0_ where classes0_.gradeid=?
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
hibernate: select classrooms0_.classid as classid1_, classrooms0_.classroomid as classroo2_1_, classroom1_.classroomid as classroo1_0_, classroom1_.classroomname as classroo2_4_0_ from schedule classrooms0_ inner join test.classroom classroom1_ on classrooms0_.classroomid=classroom1_.classroomid where classrooms0_.classid=?
hibernate: delete from test.class where classid=?
hibernate: delete from test.class where classid=?
hibernate: delete from test.grade where gradeid=?
hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
删除成功
同样,执行结果中包含了各个sql语句。
ibatis
ibatis是另外一种orm框架,和hibernate擅长操作单条记录不同,ibatis是基于sql模板的,可以说,ibatis每次和数据库进行操作时,都有明确的sql语句,而这些sql语句,就是我们定义在配置文件中的。
我们还是以test数据库中的user表为例,简单说明ibatis的操作流程:
首先,我们还是需要定义vo对象,这里还是使用和hibernate讲解时相同的user:
定义user对象
package sample.orm.ibatis;
import java.io.serializable;
public class user implements serializable
{
private static final long serialversionuid = 1l;
private int userid;
private string username;
public void setuserid(int userid) {
this.userid = userid;
}
public int getuserid() {
return userid;
}
public void setusername(string username) {
this.username = username;
}
public string getusername() {
return username;
}
}
然后需要针对这个vo,定义一个独立的配置文件:user.xml
<?xml version="1.0" encoding="utf-8"?>
<!doctype sqlmap
public "-//ibatis.com//dtd sql map 2.0//en"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlmap namespace="user">
<typealias alias="user" type="sample.orm.ibatis.user" />
<cachemodel id="user-cache" type="oscache" readonly="true" serialize="true">
<flushinterval milliseconds="1" />
<flushonexecute statement="insertuser" />
<flushonexecute statement="updateuser" />
<flushonexecute statement="getuser" />
<flushonexecute statement="getalluser" />
<property value="1" name="size" />
</cachemodel>
<!--
<resultmap >
<result property="userid" column="id" />
<result property="username" column="name" />
</resultmap>
-->
<select id="getuser" parameterclass="java.lang.integer" resultclass="user" cachemodel="user-cache" >
select id as userid,name as username from user where id = #userid#
</select>
<select id="getalluser" resultclass="user" cachemodel="user-cache">
select id as userid,name as username from user
</select>
<update id="updateuser" parameterclass="user">
update user set name=#username# where id = #userid#
</update>
<insert id="insertuser" parameterclass="user">
insert into user ( id, name ) values ( #userid#,#username#)
</insert>
<delete id="deleteuser" parameterclass="java.lang.integer">
delete from user where id=#userid#
</delete>
</sqlmap>
这个配置文件主要包括三部分:
1)缓存的配置
2)对象属性和表字段之间的关联
3)针对表的各种crud操作
然后是关于ibatis的全局配置文件sqlmapconfig.xml:
<?xml version="1.0" encoding="utf-8"?>
<!doctype sqlmapconfig
public "-//ibatis.com//dtd sql map config 2.0//en"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlmapconfig>
<settings cachemodelsenabled="true" enhancementenabled="true"
lazyloadingenabled="true" errortracingenabled="true" maxrequests="32"
maxsessions="10" maxtransactions="5" usestatementnamespaces="false" />
<transactionmanager type="jdbc">
<datasource type="simple">
<property name="jdbc.driver" value="com.mysql.jdbc.driver" />
<property name="jdbc.connectionurl" value="jdbc:mysql://localhost/test" />
<property name="jdbc.username" value="root" />
<property name="jdbc.password" value="123" />
<property name="pool.maximumactiveconnections" value="10" />
<property name="pool.maximumidleconnections" value="5" />
<property name="pool.maximumcheckouttime" value="120000" />
<property name="pool.timetowait" value="500" />
<property name="pool.pingquery" value="select 1 from user" />
<property name="pool.pingenabled" value="false" />
</datasource>
</transactionmanager>
<sqlmap resource="sample/orm/ibatis/user.xml" />
</sqlmapconfig>
和hibernate全局配置文件类似,它也包含了数据库连接的信息、数据库连接池的信息以及我们定义的user.xml。
下面是测试方法:
ibatis测试方法
public class sample {
private sqlmapclient sqlmap = null;
private void buildmap() throws ioexception
{
string resource = "sample/orm/ibatis/sqlmapconfig.xml";
reader reader = resources.getresourceasreader(resource);
this.sqlmap = sqlmapclientbuilder.buildsqlmapclient(reader);
}
private void insertuser() throws ioexception, sqlexception
{
system.out.println("=====insert test=====");
if (this.sqlmap == null)
{
this.buildmap();
}
this.sqlmap.starttransaction();
user user = new user();
user.setuserid(10);
user.setusername("angel");
this.sqlmap.insert("insertuser", user);
this.sqlmap.committransaction();
user = getuser(10);
printuserinfo(user);
}
private void updateuser() throws ioexception, sqlexception, interruptedexception
{
system.out.println("=====update test=====");
if (this.sqlmap == null)
{
this.buildmap();
}
this.sqlmap.starttransaction();
user user = new user();
user.setuserid(10);
user.setusername("devil");
this.sqlmap.update("updateuser", user);
this.sqlmap.committransaction();
this.sqlmap.flushdatacache();
// thread.sleep(3000);
user = getuser(10);
printuserinfo(user);
}
private void deleteuser() throws ioexception, sqlexception
{
system.out.println("=====delete test=====");
if (this.sqlmap == null)
{
this.buildmap();
}
sqlmap.flushdatacache();
this.sqlmap.starttransaction();
this.sqlmap.delete("deleteuser", 10);
this.sqlmap.committransaction();
getalluser();
}
private user getuser(int id) throws ioexception, sqlexception
{
if (this.sqlmap == null)
{
this.buildmap();
}
user user = (user)this.sqlmap.opensession().queryforobject("getuser", id);
return user;
}
private list<user> getalluser() throws ioexception, sqlexception
{
if(this.sqlmap==null)
this.buildmap();
list userlist=null;
userlist=this.sqlmap.opensession().queryforlist("getalluser");
printuserinfo(userlist);
return userlist;
}
private void printuserinfo(user user)
{
system.out.println("=====user info=====");
system.out.println("id:" + user.getuserid() + ";name:" + user.getusername());
}
private void printuserinfo(list<user> users)
{
system.out.println("=====user info=====");
for(user user:users)
{
system.out.println("id:" + user.getuserid() + ";name:" + user.getusername());
}
}
public static void main(string[] args) throws ioexception, sqlexception, interruptedexception
{
sample sample = new sample();
sample.getalluser();
sample.insertuser();
sample.updateuser();
sample.deleteuser();
}
}
它的执行结果如下:
=====user info=====
id:1;name:zhang san
id:2;name:test
=====insert test=====
=====user info=====
id:10;name:angel
=====update test=====
=====user info=====
id:10;name:devil
=====delete test=====
=====user info=====
id:1;name:zhang san
id:2;name:test
这篇文章只是简单介绍了hibernate和ibatis的用法,并没有涉及全部,例如hibernate的事务、拦截、hql、ibatis的缓存等等。这里主要是为了描述orm框架的基本轮廓,以及在使用方式上它和jdbc的区别。
我们在这里主要关注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的区别。