您的位置:首页 > 其它

4.2 Hibernate应用基础

2016-02-29 00:00 204 查看
摘要: Hibernate应用实例开发、Hibernate主要文件、Hibernate核心接口、HQL

1.Hibernate应用实例开发

1)建立数据库及表

本书使用SQL Server 2005数据库。在XSCJ数据库中建立KCB表。

表名:KCB

项目名列名数据类型是否可空默认值说明
课程号KCHchar(3)主键
课程名KCMchar(20)
开学学期KXXQsmallint只能为1-8
学时XSint0
学分XFint0

2)在MyEclipse中创建对SQL Server 的连接

启动MyEclipse,选择【Window】→【Open Perspective】→【MyEclipse Database Explorer】菜单项,打开MyEclipse Database浏览器,右击菜单,如图4.2所示,选择【New…】菜单项,出现如图4.3所示的对话框,编辑数据库连接驱动。

填写要建立的连接的名称“MyConn”(自定义),连接数据库的URL“jdbc:sqlserver://localhost:1433;databaseName=XSCJ”,填写数据库的用户名和密码添加数据库驱动



图4.2 MyEclipse Database浏览器,创建一个新的连接



图4.3 编辑数据库连接驱动

编辑完成以后,在MyEclipse Database浏览器中,右击刚才创建的MyConn数据库连接,选择“Open connection…”菜单项,打开名为“MyConn”的数据连接,如图4.4所示。



图4.4 打开数据库连接

3)创建Web项目,命名为“HibernateTest”

4)添加Hibernate开发能力

右击项目名HibernateTest,选择【MyEclipse】→【Add Hibernate Capabilites】菜单项,出现如图4.5所示的对话框,选择Hibernate框架应用版本及所需要的类库



图4.5 选择Hibernate版本及所需Jar包
单击【Next】按钮,进入如图4.6所示界面。创建Hibernate配置文件hibernate.cfg.xml,将该文件放在src文件夹下,后面会详细介绍该文件内容。这里先说明添加Hibernate开发功能的步骤。



图4.6 创建配置文件hibernate.cfg.xml

单击【Next】按钮,进入如图4.7所示界面,指定Hibernate数据库连接细节。由于在前面已经配置一个名为MyConn的数据库连接,所以这里只需要选择DB Driver为“MyConn”即可。



图4.7 指定hibernate数据库连接

单击【Next】按钮,出现如图4.8所示界面。Hibernate中有一个与数据库打交道重要的类Session。而这个类是由工厂SessionFactory创建的。这个界面询问是否需要创建SessionFactory类。如果需要创建,还需要指定创建的位置和类名。这些接口都会在后面详细介绍。单击【Finish】按钮,完成Hibernate的配置。



图4.8 创建SessionFactory类来简化Hibernate会话处理

5)生成数据库表对应的Java类对象和映射文件

首先在MyEclispse下创建一个名为“org.model”的包,这个包将用来存放与数据库表对应的Java类POJO。

打开MyEclipse Database Explorer视图。打开前面创建的MyConn数据连接,选择【XSCJ】→【dbo】→【TABLE】菜单项,右击KCB表,选择【Hibernate Reverse Engineering…】菜单项,如图4.9所示,将启动Hibernate Reverse Engineering向导,该向导用于完成从已有的数据库表生成对应的Java类和相关映像文件的配置工作。



图4.9 Hibernate反向工程菜单

首先,选择生成的Java类和映像文件所在的位置,如图4.10所示。POJO(Plain Old Java Object,简单的Java对象),通常也称为VO(Value Object,值对象)。 使用POJO名称是为了避免和EJB混淆起来,其中有一些属性及getter、setter方法。当然,如果有一个简单的运算属性也是可以的,但不允许有业务方法。



图4.10 生成Hibernate映射文件和Java类

单击【Next】按钮,进入如图4.11所示的界面,选择主键生成策略。



图4.11 配置反向工程细节

点击【Finish】,org.model包中会出现Kcb.java类和Kcb.hbm.xml。然后在hibernate.cfg.xml文件中配置映射文件<mapping resource="org/model/Kcb.hbm.xml"/>,该语句放在<session-factory>和</session-factory>之间。

6)创建测试类

在src文件夹下创建包test,在该包下建立测试类,命名为Test.java,其代码。

package test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.model.Kcb;
import org.util.HibernateSessionFactory;

public class Test {

public static void main(String[] args) {
// 调用HibernateSessionFactory的getSession方法创建Session对象
Session session = HibernateSessionFactory.getSession();
// 创建事务对象
Transaction ts = session.beginTransaction();
Kcb kc = new Kcb(); // 创建POJO类对象
kc.setKch("198"); // 设置课程号
kc.setKcm("机电"); // 设置课程名
kc.setKxxq(new Short((short) 5)); // 设置开学学期
kc.setXf(new Integer(5)); // 设置学分
kc.setXs(new Integer(59)); // 设置学时
// 保存对象
session.save(kc);
ts.commit(); // 提交事务
Query query = session.createQuery("from Kcb where kch=198");
List list = query.list();
Kcb kc1 = (Kcb) list.get(0);
System.out.println(kc1.getKcm());
HibernateSessionFactory.closeSession(); // 关闭Session
}

}


7)运行

因为该程序为Java Application,所以可以直接运行。运行程序,控制台就会打印出“机电”。在完全没有操作数据库的情况下,就完成了对数据的插入。下面将详细讲解各文件的作用。

2.Hibernate各种文件的作用

1)POJO类和其映射配置文件

POJO类如下:

package org.model;

public class Kcb implements java.io.Serializable {

private String kch; // 对应表中KCH字段
private String kcm; // 对应表中KCM字段
private Short kxxq; // 对应表中KXXQ字段
private Integer xs; // 对应表中XS字段
private Integer xf; // 对应表中XF字段

public Kcb() {
}
// 上述属性的getter和setter方法

}

可以发现,该类中的属性和表中的字段是一一对应的。那么通过什么方法把它们一一映射起来呢?就是前面提到的*.hbm.xml映射文件。这里当然就是Kcb.hbm.xml。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC '-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
<hibernate-mapping>
<!-- name指定POJO类,table指定对应数据库的表 -->
<class name="org.model.Kcb" table="KCB">
<!-- name指定主键,type主键类型 -->
<id name="kch" type="java.lang.String">
<column length="3" name="KCH"/>
<!-- 主键生成策略 -->
<generator class="assigned"/>
</id>
<!-- POJO属性及表中字段的对应 -->
<property name="kcm" type="java.lang.String">
<column length="12" name="KCM"/>
</property>
<property name="kxxq" type="java.lang.Short">
<column name="KXXQ"/>
</property>
<property name="xs" type="java.lang.Integer">
<column name="XS"/>
</property>
<property name="xf" type="java.lang.Integer">
<column name="XF"/>
</property>
</class>
</hibernate-mapping>


该配置文件大致分为3个部分:

(1)类、表映射配置

<class name="org.model.Kcb" table="KCB">

name属性指定POJO类为org.model.Kcb,table属性指定当前类对应数据库表KCB。

(2)id映射配置

<id name="kch" type="java.lang.String">
<column name="KCH" length="3" />
<generator class="assigned" />
</id>

id节点定义实体类的标志(assigned),在这里也就是对应数据库表主键的类属性。<generator class="assigned" />指定主键的生成方式

Hibernate的主键生成策略分为三大类:Hibernate对主键id赋值、应用程序自身对id赋值、由数据库对id赋值。

assigned:应用程序自身对id赋值。当设置<generator class="assigned"/>时,应用程序自身需要负责主键id的赋值。例如下述代码:

Kcb kc=new Kcb();    // 创建POJO类对象
kc.setKch("198");    // 设置课程号
kc.setKcm("机电");    // 设置课程名
kc.setKxxq(new Integer(5).shortValue());    // 设置开学学期
kc.setXf(new Integer(4).shortValue());    // 设置学分
kc.setXs(new Integer(59).shortValue());     // 设置学时


native:由数据库对id赋值。当设置<generator class="native"/>时,数据库负责主键id的赋值,最常见的是int型的自增型主键

hilo:通过hi/lo算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态

seqhilo:与hi/lo类似,通过hi/lo算法实现的主键生成机制,只是主键历史状态保存在sequence中,适用于支持sequence的数据库,如Oracle。

increment:主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。当有多个实例访问同一数据库时,可能造成主键重复异常。

identity:采用数据库提供的主键生成机制,如SQL Server、MySQL中的自增主键生成机制。

sequence:采用数据库提供的sequence机制生成主键,如Oracle sequence。

uuid.hex:由Hibernate基于128位唯一值产生算法,根据当前设备IP、时间、JVM启动时间、内部自增量等4个参数生成十六进制数值(编码后长度为32位的字符串表示)作为主键。即使是在多实例并发运行的情况下,这种算法在最大程度上保证了产生id的唯一性。当然,重复的概率在理论上依然存在,只是概率比较小。

uuid.string:与uuid.hex类似,只是对生成的主键进行编码(长度16位)。

foreign:使用外部表的字段作为主键。

select:Hibernate 3新引入的主键生成机制,主要针对遗留系统的改造工程

(3)属性、字段映射配置

属性、字段映射将映射类属性与库表字段相关联。

<property name="kcm" type="java.lang.String">
<column name="KCM" length="12" />
</property>

name="kcm" 指定映像类中的属性名为“kcm”,此属性将被映像到指定的库表字段KCM。type="java.lang.String"指定映像字段的数据类型。column name="KCM"指定类的kcm属性映射KCB表中的KCM字段。

2)hibernate.cfg.xml文件

该文件是Hibernate重要的配置文件,配置该文件主要是配置SessionFractory类

<?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>
<!-- 数据库连接的URL -->
<property name="connection.url">jdbc:sqlserver://localhost:1433;databaseName=XSCJ</property>
<!-- 数据库连接的用户名,此处为自己数据库的用户名和密码 -->
<property name="connection.username">liuyanbo</property>
<!-- 数据库连接的密码 -->
<property name="connection.password">123456</property>
<!-- SQL方言,这里使用的是SQL Server -->
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<!-- 使用的数据库的连接,我们创建的MyConn -->
<property name="myeclipse.connection.profile">MyConn</property>
<!-- 数据库JDBC驱动程序 -->
<property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<!-- 表和类对应的映射文件,如果多个,都要在这里注册 -->
<mapping resource="org/model/Kcb.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Hibernate配置文件主要用于配置数据库连接和Hibernate运行时所需要的各种属性。Hibernate初始化期间会自动在CLASSPATH中寻找这个文件,并读取其中的配置信息,为后期数据库操作做好准备。

3)HibernateSessionFactory

HibernateSessionFactory类是自定义的SessionFactory名字可以自定义。这里用的HibernateSessionFactory。

package org.util;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactory {

// 定义一个静态字符串变量存放Hibernate的配置文件名
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
// 创建一个线程局部变量对象
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
// 创建一个静态的Configuration对象
private static Configuration configuration = new Configuration();
// 定义一个静态的SessionFactory对象
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
// 根据配置文件得到SessionFactory对象

static {
try {
// 得到configuration对象
// 该句和上面创建的静态对象合起来就为
// configuration=new Configuration().configure(configFile);
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}

// 取得Session对象
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}

// 可以调用该方法重新创建SessionFactory对象
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}

// 关闭Session
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}

public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}

public static Configuration getConfiguration() {
return configuration;
}

}

在Hibernate中,Session负责完成对象持久化操作。该文件负责创建Session对象,以及关闭Session对象。从该文件可以看出,Session对象的创建大致需要以下3个步骤:

① 初始化Hibernate配置管理类Configuration。

② 通过Configuration类实例创建Session的工厂类SessionFactory。

③ 通过SessionFactory得到Session实例。

3.Hibernate核心接口

1)Configuration接口

Configuration负责管理Hibernate的配置信息。Hibernate运行时需要一些底层实现的基本信息。这些信息包括:数据库URL、数据库用户名、数据库用户密码、数据库JDBC驱动类、数据库dialect。用于对特定数据库提供支持,其中包含了针对特定数据库特性的实现,如Hibernate数据库类型到特定数据库数据类型的映射等。

使用Hibernate必须首先提供这些基础信息以完成初始化工作,为后续操作做好准备。这些属性在Hibernate配置文件hibernate.cfg.xml中加以设定,当调用:

Configuration config=new Configuration().configure();

时,Hibernate会自动在目录下搜索hibernate.cfg.xml文件,并将其读取到内存中作为后续操作的基础配置

2)SessionFactory接口

SessionFactory负责创建Session实例,可以通过Configuration实例构建SessionFactory。

Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buildSessionFactory();

Configuration实例config会根据当前的数据库配置信息,构造SessionFacory实例并返回。SessionFactory一旦构造完毕,即被赋予特定的配置信息。就是说,之后config的任何变更将不会影响到已经创建的SessionFactory实例sessionFactory。如果需要使用基于变更后的config实例的SessionFactory,需要从config重新构建一个SessionFactory实例。如果需要访问多个数据库,针对每个数据库,应分别创建其对应的SessionFactory实例。

SessionFactory保存了对应当前数据库配置的所有映射关系,同时也负责维护当前的二级数据缓存和Statement Pool。由此可见,SessionFactory的创建过程非常复杂、代价高昂。这也意味着,在系统设计中充分考虑到SessionFactory的重用策略。由于SessionFactory采用了线程安全的设计,可由多个线程并发调用。大多数情况下,针对一个数据库共享一个SessionFactory实例即可。

3)Session接口

Session是Hibernate持久化操作的基础提供了众多持久化方法,如save、update、delete等。通过这些方法,透明地完成对象的增加、删除、修改、查找等操作。

同时,值得注意的是,Hibernate Session的设计是非线程安全的,即一个Session实例同时只可由一个线程使用。同一个Session实例的多线程并发调用将导致难以预知的错误。

Session实例由SessionFactory构建:

Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buldSessionFactory();
Session session=sessionFactory.openSession();


4)Transaction接口

Transaction是Hibernate中进行事务操作的接口,Transaction 接口是对实际事务实现的一个抽象,这些实现包括JDBC的事务、JTA 中的UserTransaction,甚至可以是CORBA 事务。之所以这样设计是可以让开发者能够使用一个统一的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移值。事务对象通过Session创建。例如以下语句:

Transaction ts=session.beginTransaction();


5)Query接口

在Hibernate 2.x中,find()方法用于执行HQL语句。Hibernate 3.x废除了find()方法,取而代之的是Query接口,它们都用于执行HQL语句。Query和HQL是分不开的。

Query query=session.createQuery(“from Kcb where kch=198”);

上面是直接给出查询条件的值,也可以是设参数,例如以下语句:

Query query=session.createQuery("from Kcb where kch=?");

就要在后面设置其值:

Query.setString(0, "要设置的值");

上面的方法是通过“?”来设置参数,还可以用“:”后跟变量的方法来设置参数,如上例可以改为:

Query query=session.createQuery("from Kcb where kch=:kchValue");
Query.setString("kchValue","要设置的课程号值");

由于上例中kch为String类型,所以要用setString(),如果是int型,就要用setInt()。通用的方法是setParameter()方法,不管是什么类型的参数都可以。其使用方法是相同的,例如:

Query.setParameter(0, "要设置的值");

Query还有一个list()方法,用于取得一个List集合的示例,此示例中包括可能是一个Object集合,也可能是Object数组集合。例如:

Query query=session.createQuery("from Kcb where kch=198");
List list=query.list();


4.HQL查询

Hibernate Query Language。语法与SQL很像,但HQL是一种面向对象的查询语言SQL的操作对象是数据表和列等数据对象,而HQL的操作对象是类、实例、属性等。HQL的查询依赖于Query类,每个Query实例对应一个查询对象。

Query query=session.createQuery(“from Kcb where kch=198”);

HQL常用的几种查询方式:

1)基本查询

基本查询是HQL中最简单的一种查询方式。下面以课程信息为例说明其几种查询情况。

(1)查询所有课程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
Query query=session.createQuery("from Kcb");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

(2)查询某门课程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询一门学时最长的课程
Query query=session.createQuery("from Kcb order by xs desc");
query.setMaxResults(1);                        // 设置最大检索数目为1
// 装载单个对象
Kcb kc=(Kcb)query.uniqueResult();
ts.commit();
HibernateSessionFactory.closeSession();

(3)查询满足条件的课程信息

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询课程号为001的课程信息
Query query=session.createQuery("from Kcb where kch=001");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


2)条件查询

查询的条件有几种情况,下面举例说明。

(1)按指定参数查询

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询课程名为计算机基础的课程信息
Query query=session.createQuery("from Kcb where kcm=?");
query.setParameter(0, "计算机基础");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();

(2)使用范围运算查询

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询这样的课程信息,课程名为计算机基础或数据结构,且学时在40~60之间
Query query=session.createQuery("from Kcb where (xs between 40 and 60) and kcm in('计算机基础','数据结构')");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


(3)使用比较运算符查询

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询学时大于51且课程名不为空的课程信息
Query query=session.createQuery("from Kcb where xs>51 and kcm is not null");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


(4)使用字符串匹配运算查询

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
// 查询课程号中包含“001”字符串且课程名前面三个字为计算机的所有课程信息
Query query=session.createQuery("from Kcb where kch like '%001%' and kcm like '计算机%'");
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


3)分页查询

为了满足分页查询的需要,Hibernate的Query实例提供了两个有用的方法:setFirstResult(int firstResult)和setMaxResults(int maxResult)。其中setFirstResult(int firstResult)方法用于指定从哪一个对象开始查询(序号从0开始),默认为第1个对象,也就是序号0。SetMaxResults(int maxResult)方法用于指定一次最多查询出的对象的数目,默认为所有对象。如下面的代码片段:

Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
Query query=session.createQuery("from Kcb");
int pageNow=1;                                // 想要显示第几页
int pageSize=5;                                // 每页显示的条数
query.setFirstResult((pageNow-1)*pageSize);                // 指定从哪一个对象开始查询
query.setMaxResults(pageSize);                        // 指定最大的对象数目
List list=query.list();
ts.commit();
HibernateSessionFactory.closeSession();


附:目录《JavaEE基础实用教程》笔记说明
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Hibernate