基于Java ORM框架的使用詳解
我們?cè)谶@里主要關(guān)注Java中常用的兩個(gè)ORM框架:Hibernate和iBatis。下面來介紹這兩個(gè)框架簡(jiǎn)單的使用方法,如果將來有時(shí)間,我會(huì)深入的寫一些更有意思的相關(guān)文章。
Hibernate
Hibernate是一個(gè)持久化框架和ORM框架,持久化和ORM是兩個(gè)有區(qū)別的概念,持久化注重對(duì)象的存儲(chǔ)方法是否隨著程序的退出而消亡,ORM關(guān)注的是如何在數(shù)據(jù)庫表和內(nèi)存對(duì)象之間建立關(guān)聯(lián)。
Hibernate使用POJO來表示Model,使用XML配置文件來配置對(duì)象和表之間的關(guān)系,它提供了一系列API來通過對(duì)對(duì)象的操作而改變數(shù)據(jù)庫中的過程。
Hibernate更強(qiáng)調(diào)如何對(duì)單條記錄進(jìn)行操作,對(duì)于更復(fù)雜的操作,它提供了一種新的面向?qū)ο蟮牟樵冋Z言:HQL。
我們先來定義一個(gè)關(guān)于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();
}
}
}
基于單張表進(jìn)行操作
下面我們來看一個(gè)簡(jiǎn)單的示例,它沿用了<基于Java回顧之JDBC的使用詳解>中的數(shù)據(jù)庫,使用MySQL的test數(shù)據(jù)庫中的user表。
首先,我們來定義VO對(duì)象:
定義User對(duì)象
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對(duì)象和數(shù)據(jù)庫中user表之間的關(guān)聯(lián),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>
將上述內(nèi)容存儲(chǔ)為User.hbm.xml。
接下來,我們需要定義一個(gè)關(guān)于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>
可以看到,上述配置文件中包含了數(shù)據(jù)庫連接的信息,諸如driver信息、數(shù)據(jù)庫url、用戶名、密碼等等,還包括了我們上面定義的User.hbm.xml。
最后,我們編寫測(cè)試代碼,來對(duì)user表進(jìn)行增、刪、查、改的操作:
使用Hibernate對(duì)user表進(jìn)行操作
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();
}
我們按照如下順序調(diào)用測(cè)試代碼:
insertUser();
updateUser(6);
deleteUser(6);
可以看到如下結(jié)果:
=====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.
請(qǐng)注意,上面的結(jié)果中,輸出了每次數(shù)據(jù)庫操作時(shí)的SQL語句,這是因?yàn)樵谂渲梦募杏腥缦屡渲茫?BR>
<property name="show_sql">true</property>
我們可以在開發(fā)調(diào)試階段將其打開,在部署到客戶方時(shí),將其關(guān)閉。
基于多表關(guān)聯(lián)的操作
Hibernate在建立多表關(guān)聯(lián)時(shí),根據(jù)主外鍵的設(shè)置,表之間的關(guān)聯(lián)可以分為三種:一對(duì)一、一對(duì)多和多對(duì)多。這些關(guān)聯(lián)會(huì)體現(xiàn)在表的配置文件以及VO中。
下面我們來看一個(gè)經(jīng)典的多表關(guān)聯(lián)示例:排課表。數(shù)據(jù)庫中建立如下四張表:Grade/Class/ClassRoom/Schedule。剛發(fā)現(xiàn),使用MySQL自帶的管理器導(dǎo)出表定義基本是一件不可能的任務(wù)。。。。
上述各表除ID以及必要外鍵外,只有Name一列。
然后看各個(gè)VO的定義:
定義Grade對(duì)象
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對(duì)象
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對(duì)象
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對(duì)象
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;
}
}
接著是各個(gè)表的關(guān)聯(lián)配置文件:
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>節(jié)點(diǎn)說明了Grade和Class之間一對(duì)多的關(guān)系。
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>
注意它定義兩個(gè)關(guān)聯(lián):一個(gè)是和Grade之間多對(duì)一的關(guān)系,一個(gè)適合ClassRoom之間多對(duì)多的關(guān)系。
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>
它只定義了一個(gè)關(guān)聯(lián):和Class之間的多對(duì)多關(guān)聯(lián)。
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>
這里就不需要再定義關(guān)聯(lián)了。
我們需要在Hibernate全局配置文件中添加如下內(nèi)容:
<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" />
下面是各種測(cè)試方法,在有關(guān)聯(lián)的情況下,Hibernate提供了下面幾個(gè)特性:
•延遲加載
•級(jí)聯(lián)添加
•級(jí)聯(lián)修改
•級(jí)聯(lián)刪除
多表關(guān)聯(lián)情況下的一些測(cè)試方法
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("年級(jí):" + grade.getGradeName() + "包括以下班級(jí):");
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("四年級(jí)");
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);
}
按順序調(diào)用上面的方法:
getClass(1);
getSchedule(1);
insertGrade();
updateGrade1(4);
updateGrade2(4);
deleteGrade(10);
執(zhí)行結(jié)果如下:
=====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=?
年級(jí):一年級(jí)包括以下班級(jí):
一年級(jí)二班
一年級(jí)一班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
ID:1; Name:一年級(jí)
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=?
一年級(jí)一班使用以下教室:
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=?
教室二
教室五
教室一
一年級(jí)二班使用以下教室:
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=?
年級(jí):四年級(jí)包括以下班級(jí):
四年級(jí)二班
四年級(jí)一班
Hibernate: select grade0_.gradeid as gradeid0_, grade0_.gradename as gradename1_0_ from test.grade grade0_ where grade0_.gradeid=?
ID:4; Name:四年級(jí)
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=?
年級(jí):Grade 4包括以下班級(jí):
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=?
年級(jí):Grade 4包括以下班級(jí):
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=?
刪除成功
同樣,執(zhí)行結(jié)果中包含了各個(gè)SQL語句。
iBatis
iBatis是另外一種ORM框架,和Hibernate擅長(zhǎng)操作單條記錄不同,iBatis是基于SQL模板的,可以說,iBatis每次和數(shù)據(jù)庫進(jìn)行操作時(shí),都有明確的SQL語句,而這些SQL語句,就是我們定義在配置文件中的。
我們還是以test數(shù)據(jù)庫中的user表為例,簡(jiǎn)單說明iBatis的操作流程:
首先,我們還是需要定義VO對(duì)象,這里還是使用和Hibernate講解時(shí)相同的User:
定義User對(duì)象
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;
}
}
然后需要針對(duì)這個(gè)VO,定義一個(gè)獨(dú)立的配置文件: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>
這個(gè)配置文件主要包括三部分:
1)緩存的配置
2)對(duì)象屬性和表字段之間的關(guān)聯(lián)
3)針對(duì)表的各種CRUD操作
然后是關(guān)于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全局配置文件類似,它也包含了數(shù)據(jù)庫連接的信息、數(shù)據(jù)庫連接池的信息以及我們定義的User.xml。
下面是測(cè)試方法:
iBatis測(cè)試方法
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();
}
}
它的執(zhí)行結(jié)果如下:
=====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
這篇文章只是簡(jiǎn)單介紹了Hibernate和iBatis的用法,并沒有涉及全部,例如Hibernate的事務(wù)、攔截、HQL、iBatis的緩存等等。這里主要是為了描述ORM框架的基本輪廓,以及在使用方式上它和JDBC的區(qū)別。
相關(guān)文章
Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui詳解
這篇文章主要介紹了Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui,本文簡(jiǎn)要介紹一款基于Mybatis-Plus的代碼自助生成器,文章通過實(shí)例集成的方式來詳細(xì)講解mybatis-plus-generator-ui,從相關(guān)概念到實(shí)際集成案例,以及具體的擴(kuò)展開發(fā)介紹,需要的朋友可以參考下2022-11-11Java BufferedOutputStream類的常用方法講解
這篇文章主要介紹了Java BufferedOutputStream類的常用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Spring Cloud gateway 網(wǎng)關(guān)如何攔截Post請(qǐng)求日志
這篇文章主要介紹了Spring Cloud gateway 網(wǎng)關(guān)如何攔截Post請(qǐng)求日志的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07SpringMVC通過RESTful結(jié)構(gòu)實(shí)現(xiàn)頁面數(shù)據(jù)交互
RESTFUL是一種網(wǎng)絡(luò)應(yīng)用程序的設(shè)計(jì)風(fēng)格和開發(fā)方式,基于HTTP,可以使用XML格式定義或JSON格式定義。RESTFUL適用于移動(dòng)互聯(lián)網(wǎng)廠商作為業(yè)務(wù)接口的場(chǎng)景,實(shí)現(xiàn)第三方OTT調(diào)用移動(dòng)網(wǎng)絡(luò)資源的功能,動(dòng)作類型為新增、變更、刪除所調(diào)用資源2022-08-08java實(shí)現(xiàn)圖的鄰接表存儲(chǔ)結(jié)構(gòu)的兩種方式及實(shí)例應(yīng)用詳解
這篇文章主要介紹了java實(shí)現(xiàn)圖的鄰接表存儲(chǔ)結(jié)構(gòu)的兩種方式及實(shí)例應(yīng)用詳解,鄰接表構(gòu)建圖是必須需要一個(gè)Graph對(duì)象,也就是圖對(duì)象!該對(duì)象包含屬性有:頂點(diǎn)數(shù)、邊數(shù)以及圖的頂點(diǎn)集合,需要的朋友可以參考下2019-06-06java使用EasyExcel實(shí)現(xiàn)Sheet的復(fù)制與填充
EasyExcel是一個(gè)非常有用的工具,它提供了強(qiáng)大的模板填充功能,可以輕松解決各種業(yè)務(wù)需求,本文主要為大家介紹了如何使用EasyExcel實(shí)現(xiàn)模板Sheet復(fù)制與填充,需要的可以參考下2023-10-10Java實(shí)現(xiàn)PDF轉(zhuǎn)HTML/Word/Excel/PPT/PNG的示例代碼
這篇文章主要為大家介紹了如何利用Java語言是PDF轉(zhuǎn)HTML、Word、Excel、PPT和PNG功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-05-05