4.2 Hibernate应用基础

1.Hibernate应用实例开发

1)创建数据库及表

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

表名:KCB算法

项目名sql

列名数据库

数据类型数组

是否可空浏览器

默认值缓存

说明安全

课程号session

KCH数据结构

char(3)



主键

课程名

KCM

char(20)



开学学期

KXXQ

smallint


只能为1-8

学时

XS

int

0


学分

XF

int

0


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所示。POJOPlain Old Java Object,简单的Java对象),一般也称为VOValue 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:使用外部表的字段做为主键

  • selectHibernate 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基础实用教程》笔记说明

相关文章
相关标签/搜索