Kela's Blog

            前面的路很坎坷,但毕竟是条路.也许走过这一段就会发现,走过去就是梦想中的地方.因此坚持成为此刻唯一能做且必须去做的事情.
posts - 9, comments - 27, trackbacks - 0, articles - 15

kela的笔记 ORM产品 ---- hibernate(3)

Posted on 2005-11-22 13:02 Kela 阅读(2316) 评论(2)  编辑  收藏 所属分类: 我的笔记(Hibernate)

一个Hibernate版本的“Hello World”

1. 搭建环境
     建立项目:名称为HibernateProject,如下图:
     hb001.BMP
      下载Hibernate发行包:
       这里使用 Hibernate3.X ,因为 Hibernate 在3.X 上性能有了更大的提升。(也可以采用 2. X的版本,3.X 和 2.X 之间的差异不多,这里的“不多”是从使用者的角度来看,在需要注意的地方,会注明,另附 3.X 和 2.X 差异表一张)
      下载地址:http://www.hibernate.org 在 http://www.redsaga.com 的努力之下,Hibernate 的官方发行包中( doc\reference 下),始终有高质量的中文官方文档,非常的感谢他们。
      在ClassPath 中设置系统开发需要的类库:
      在项目的lib目录下添加以下类包( .jar) 文件,并且将这些 .jar 指定在系统 ClassPath 中。(总之,无论在哪种环境中都必须保证系统能找到我们设置的 .jar 。
        a.数据库驱动程序
           数据库使用 MS SQL SERVER ,以下是MS 的 JDBC 驱动。( MS 的 JDBC 驱动不是 Hibernate 官方的推荐驱动,在实际的项目中,朋友们可以根据 Hibernate  开发文档中的配置说明进行取舍)   
           msbase.jar,  mssqlserver.jar, msutil.jar
        b.Hibernate 3.X 的类库
           将发行包下的 hibernate3.jar 文件复制到 项目(HibernateProject)的 lib 目录下。
        c.Hibernate需要的第三方类库
           将发行包下 lib 目录下的 .jar 文件复制到项目(HibernateProject)的 lib 目录下。
           需要注意的是,我们这里将全部的 .jar 放在了lib中,在实际的开发中可以根据文档配置的说明,进行选择。
       
2. 建立数据库
    数据库名称:hbdb
create database hbdb;
    数据表名称:KELA_STUDENT  
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[KELA_STUDENT]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[KELA_STUDENT]
GO

CREATE TABLE [dbo].[KELA_STUDENT] (
 [StuID] [varchar] (32) COLLATE Chinese_PRC_CI_AS NOT NULL ,        -- PK
 [StuName] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,            --学生姓名
 [StuSex] [char] (1) COLLATE Chinese_PRC_CI_AS NULL ,                      --学生性别
 [StuAge] [smallint] NULL ,                                                                             --学生年龄
 [StuAddress] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL         --学生地址
) ON [PRIMARY]
GO

3. 将 发行包下 ehcache.xml 文件复制到 src 下 
    在Hibernate3中, 如果没有这个文件会出现
        WARN Configurator:126 - No configuration found. Configuring ehcache from ehcache-failsafe.xml found in
         the classpath: jar:file:/D:/J2eeProject/HibernateProject/lib/ehcache-1.1.jar!/ehcache-failsafe.xml
        的错误。
    该文件为 Hibernate 的本身的 Cache 配置。
4. Hibernate 配置
    Hibernate 配置文件主要用于配置数据库连接和Hibernate运行时所需要的各种属性(如,连接池,SQL方言,是否现实SQL日志等)。
    Hibernate 同时支持 xml 格式的配置文件各传统的 properties 文件配置形式,这里采用 xml 。
    配置文件名默认为 hibernate.cfg.xml(或 hibernage.properties),Hibernate在初始化期间自动在 classPath中寻找这个文件,并读取其中的配置信息,并加载。
    以下是 hibernate.cfg.xml 文件(在项目 HibernateProject 的src 下放以下内容):
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
 <session-factory>
  
  <!-- 是否将运行期生成的SQL输出到日志以供调试 -->
  <property name="hibernate.show_sql">
   true
  </property>
  
  <!-- SQL 方言-->
  <property name="hibernate.dialect">
   org.hibernate.dialect.SQLServerDialect
  </property>
  
  <!-- 数据库用户 -->
  <property name="hibernate.connection.username">
   sa
  </property>
  
  <!-- 数据库密码 -->
  <property name="hibernate.connection.password">
   123456
  </property>
  
  <!-- 数据库 JDBC 驱动-->
   <property name="hibernate.connection.driver_class">
   com.microsoft.jdbc.sqlserver.SQLServerDriver
  </property>
  
  <!-- 数据库 URL -->
  <property name="hibernate.connection.url">
   jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=hbdb
  </property>
  
  <!-- 事务管理类型 -->
  <!-- Hibernate 3 对包名做了修改 ( net.sf.hibernate  => org.hibernate )-->
  <property name="hibernate.transaction.factory_class">
   org.hibernate.transaction.JDBCTransactionFactory
  </property>
  
  <!-- c3p0 连接池 -->
  <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
  <property name="hibernate.c3p0.max_size">2</property>
  <property name="hibernate.c3p0.min_size">2</property>
  <property name="hibernate.c3p0.timeout">50000</property>
  <property name="hibernate.c3p0.max_statements">100</property>
  <property name="hibernate.c3p0.idle_test_period">3000</property>
  <property name="hibernate.c3p0.acquire_increment">2</property>
  <property name="hibernate.c3p0.validate">false</property>
 
  
  <!-- 映射的配置文件,对应数据库表 KELA_STUDENT 的映射文件,在后面将看到这个文件的配置 -->
  <mapping resource="com/kela/hb/pojo/KelaStudent.hbm.xml"/>
 </session-factory>
</hibernate-configuration>

5. 日志配置
在Hibernate发行包的etc目录下找到 log4j.properties 示例配置文件,可以修改其中的日志级别,也可直接使用。
在src下,放置 log4j.properties 文件,内容如下:
# log4j #
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=warn, stdout

#设置显示 error以上级别log
log4j.logger.org.hibernate=error 

6. 构建 POJO 类和Hibernate映射( .hbm.xml)文件
        说明:根据数据库定义导出表结构,并自动生成对应的映射文件和POJO java代码,是实际开发当中最常用的方式,也是专家所推荐的。可以使用 MiddleGen -- Hibernate,Hibernate -- Extensions 等的工具,这些工具的使用非常的方便,只修修改相应的 ant 构建文件即可,在网络上可以很容易的找到这些工具的使用方法。
        这里采用手工编写 POJO 和映射文件的方法,是基于开发者更好理解 Hibernate 运作机制而考虑。付出手工编写会产生疏漏和错误的代价,我觉得在学习阶段是值得的。
      以下是这两个文件,他们的位置都在   com.kela.hb.pojo 下面。
POJO类:com.kela.hb.pojo.KelaStudent
 /**
  * KelaStudent.java
  */
package com.kela.hb.pojo;

import java.io.Serializable;

public class KelaStudent implements Serializable {

 private static final long serialVersionUID = 8365163573354176897L;
 
 String stuID;
 String stuName;
 String stuSex;
 Integer stuAge;
 String stuAddress;
 
 public KelaStudent() {
  
 }

 public String getStuAddress() {
  return stuAddress;
 }

 public void setStuAddress(String stuAddress) {
  this.stuAddress = stuAddress;
 }

 public Integer getStuAge() {
  return stuAge;
 }

 public void setStuAge(Integer stuAge) {
  this.stuAge = stuAge;
 }

 public String getStuID() {
  return stuID;
 }

 public void setStuID(String stuID) {
  this.stuID = stuID;
 }

 public String getStuName() {
  return stuName;
 }

 public void setStuName(String stuName) {
  this.stuName = stuName;
 }

 public String getStuSex() {
  return stuSex;
 }

 public void setStuSex(String stuSex) {
  this.stuSex = stuSex;
 }
}

映射文件:KelaStudent.hbm.xml
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
 
 <class name="com.kela.hb.pojo.KelaStudent" table="KELA_STUDENT">
  
  <!-- id 节点配置了表的主键-->
  <id
   name="stuID"                  //POJO类指的ID
   column="StuID"              //数据库中的主键名称
   type="java.lang.String"    //字符类型
  >
    <generator class="uuid.hex"/>   //这里的uuid.hex代表了一种主键的生成方式
  </id>
  
   <property
        name="stuName"       //POJO中的属性
      column="StuName"     //属性对应数据库字段的名称
      type="java.lang.String" //属性类型
     />
  
  <property
      name="stuSex"
      column="StuSex"
      type="java.lang.String"
     />
  
  <property
      name="stuAge"
      column="StuAge"
      type="java.lang.Integer"
     />
  
  <property
      name="stuAddress"
      column="StuAddress"
      type="java.lang.String"
     />
  
 </class>
</hibernate-mapping>

7. 测试代码
HelloTest  . java

package com.kela.test;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.kela.hb.pojo.KelaStudent;
import com.kela.hb.util.HibernateUtil;

public class HelloTest {

    Session session = null;
 
     public void testInsert() {

        Transaction tran = null;

        try {

           //从  HibernateUtil 得到 hibernate的session,  HibernateUtil .java 文件在后
           session = HibernateUtil.currentSession();
           //启动事务
           tran = session.beginTransaction();
   
           KelaStudent kelaStudent = new KelaStudent();
           //插入数据
           kelaStudent.setStuName("王小二");
           kelaStudent.setStuSex("T");
           kelaStudent.setStuAge(new Integer(26));
           kelaStudent.setStuAddress("甘肃兰州");
          
           //保存并提交事务
           session.save(kelaStudent);
           session.flush();
           tran.commit();
   
        } catch (HibernateException he){
   
           System.out.println("运行中发生了错误");
           try {
               HibernateUtil.closeSession();
           } catch (HibernateException he2) {
               System.out.println("关闭 session 没有成功");
           }
        }
 
    }
 
    public static void main(String[] args) {
        System.out.println(" ========= 开始测试 ==========");
        HelloTest helloTest = new HelloTest();
        helloTest.testInsert();
        System.out.println(" ========= SUCCESS ==========");
    }

}

下面是 HibernateUtil  . java
/**
 * HibernateUtil.java
 */
package com.kela.hb.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

   private static Log log = LogFactory.getLog(HibernateUtil.class);

   private static final SessionFactory sessionFactory;

   static {
       try {
           sessionFactory = new Configuration().configure().buildSessionFactory();
       } catch (Throwable ex) {
           log.error("初始化 SessionFactory 发生错误.", ex);
           throw new ExceptionInInitializerError(ex);
       }
    }

     public static final ThreadLocal session = new ThreadLocal();

     public static Session currentSession() {
         Session s = (Session) session.get();
         if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);
        }
     return s;
    }

    public static void closeSession() {
        Session s = (Session) session.get();
        if (s != null)
           s.close();
        session.set(null);
    }

}

8. 运行结果
    运行 HelloTest.java 文件,观察数据库中的结果,可以看到一条数据被添加了进来。

   数据库结果:
   402880fc07c68f690107c68f6dfd0001          王小二         T         26         甘肃兰州
   
   在控制台看到如下日志:
    Hibernate:
    insert into KELA_STUDENT (StuName, StuSex, StuAge, StuAddress, StuID) values (?, ?, ?, ?, ?)
  
    就是这么神奇。不需要指定 SQL 语句一样能实现SQL的功能。

9. 关于测试代码的解释
    在Hibernate中session完成持久化操作,要创建一个Session实例大致需要3个步骤:
    A. 初始化Hibernate配置管理类Configuration

         //读入默认的配置文件(hibernate.cfg.xml 或 hibernate.properties)来创建一个Configuration
         Configuration config = new Configuration().configure();  
    B. 通过Configuration类的实例来创建 Session 的工厂类 SessionFactory:
        
         SessionFactory sessionFactory = config.buildSessionFactory();

    C. 通过SessionFactory得到Session实例:
  
         session = sessionFactory.openSession();

    D. 通过Session实例完成持久化操作:

           //启动事务
           tran = session.beginTransaction();
   
           KelaStudent kelaStudent = new KelaStudent();
           //插入数据
           kelaStudent.setStuName("王小二");
           kelaStudent.setStuSex("T");
           kelaStudent.setStuAge(new Integer(26));
           kelaStudent.setStuAddress("甘肃兰州");
          
           //保存并提交事务
           session.save(kelaStudent);
           session.flush();
           tran.commit();

      说明:由于SessionFactory采取了线程安全的设计,可以有多个线程并发调用,大多数情况下,一个应用中针对一个数据库共享一个SessionFactory实例即可。
                  Session(这里的Session是Hibernate的Session)可以理解成相当于JDBC 的Connection),它的设计是非线程安全的也就是说一个Session实例只可以由一个线程使用。
                  有了以上两点的考虑,在 HelloTest.java中在得到Session实例使用了:

           //从  HibernateUtil 得到 hibernate的session,  HibernateUtil .java 文件在后
           session = HibernateUtil.currentSession();

          
           在HibernateUtil.java 文件中创建Session,关闭Session。(这段代码来自于Hibernate文档)
           这就相当于我们平时从数据库连接池中得到 Connection,用完了 close.conn() 是一样的道理。

    

Feedback

# re: kela的笔记 ORM产品 ---- hibernate(3)  回复  更多评论   

2005-11-23 16:31 by
封装一个hibernate的DAO调用模版,就像spring的HibernateDaoSupport一样,这样,代码就会优美很多,楼主有时间的话实现一个。

# re: kela的笔记 ORM产品 ---- hibernate(3)  回复  更多评论   

2005-11-23 16:33 by brother
同样,可以利用callback实现自己的aop,也建议你尝试一下。

只有注册用户登录后才能发表评论。


网站导航:
 
分享到: