« Java读写Excel简介 | Main | JavaFX对比主流RIA技术 »
http://developers.sun.com.cn/blog/functionalca/date/20090411 星期六 2009年04月11日

Hibernate简介

Hibernate简介
作者:曹祺
Email:Qi.Cao@Sun.Com
Blog: http://blogs.sun.com/greysh 
本文难度:入门 
本文链接: http://developers.sun.com.cn/blog/functionalca/entry/hibernate%E7%AE%80%E4%BB%8B  
源代码下载: 
http://developers.sun.com.cn/blog/functionalca/resource/Greysh/FCA_Greysh_Hibernate.part1.rar 
http://developers.sun.com.cn/blog/functionalca/resource/Greysh/FCA_Greysh_Hibernate.part2.rar 
http://developers.sun.com.cn/blog/functionalca/resource/Greysh/FCA_Greysh_Hibernate.part3.rar


Hibernate官方网站: http://www.hibernate.org  

简介
Helloworld

在众多的ORM解决方案中,
hibernate无疑是使用最广的ORM框架,
自动化的生成sql语句虽然在某些地方失去了灵活性
但是对于大部分情况来说,提高了开发效率
当然也支持原生的SQL查询。
本教程主要是hibernate的流程的简单概述
如果想了解高级用处,请查阅hibernate手册
也可以去满江红开源社区下载hibernate开发指南

目前最新的版本为hibernate core为3.3.1.GA
当然hibernate其他附属包的最新版本为4.0(如hibernate-annotations-3.4.0.GA)
读者在使用的时候,如果用的hibernate-distribution-3.3.1.GA-dist
则需要将hibernate-annotations-3.4.0.GA的slf4j-log4j12.jar,slf4j-api.jar,log4j.jar
加到环境变量,否则会报异常

ejb3有很多体现hibernate的思想(当然,hibernate的作者参与了EJB3的制订)

Helloworld
本教程写了一个最简单的Helloworld
已经保证项目的最精简
文件清单如下
│  hibernate.cfg.xml
│  log4j.properties
│ 
└─com
    └─greysh
        └─hibernate
                Test.java
                User.hbm.xml
                User.java

为方便读者理解,数据库仅仅有三个字段,模拟用户注册,采用的MySQL

CREATE TABLE `user` (
  `USER_ID` int(11) NOT NULL auto_increment,
  `USER_NAME` varchar(255) NOT NULL,
  `USER_PASSWORD` varchar(255) NOT NULL,
  PRIMARY KEY  (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

hibernate的工厂配置文件
<?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.username">root</property>
 <property name="connection.url">
  jdbc:mysql://localhost:3306/hibernate
 </property>
 <property name="dialect">
  org.hibernate.dialect.MySQLDialect
 </property>
 <property name="connection.password">root</property>
 <property name="connection.driver_class">
  com.mysql.jdbc.Driver
 </property>
 <property name="show_sql">true</property>
 <mapping resource="com/greysh/hibernate/User.hbm.xml" />
</session-factory>
</hibernate-configuration>

dialect为hibernate的方言,因为不同的数据库虽然支持SQL标准,但是不同厂商也有自己的特定的SQL语句,hibernate用方言进行了统一,在切换数据库的时候只需要修改方言,很方便。show_sql是在控制台打印HQL底层的SQL。Hibernate默认的连接池是C3P0.尽管hibernate的底层调用的是jdbc,但是做了很多缓存的优化,因此读者在使用的时候,可能感觉hibernate比直接的jdbc性能要高,那是因为采取了很多优化。
当然,这里也可以写hibernate.properties文件,但是xml的扩展性要比properties好,所以笔者建议读者采用xml的配置方式

hibernate的日志用的是slf4j/log4j,因此需要配置log4j
log4j.properties如下
log4j.rootLogger=INFO,consoleAppender
log4j.addivity.org.apache=true
log4j.appender.logfile.Append = true  
log4j.appender.logfile.MaxFileSize = 1MB
log4j.appender.logfile.layout = org.apache.log4j.HTMLLayout
log4j.appender.logfile.layout.LocationInfo = true
log4j.appender.errorlogfile.DatePattern = ' . ' yyyy - MM - dd ' .log '
log4j.appender.errorlogfile.layout = org.apache.log4j.PatternLayout
log4j.appender.errorlogfile.layout.ConversionPattern =%d %p [ %c] -   %m %n %d
log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.Threshold = ERROR
log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern =%d %-5p %m %n
log4j.appender.consoleAppender.ImmediateFlush = true
log4j.appender.consoleAppender.Target =System.out

然后是实体类User.java
package com.greysh.hibernate;

public class User {

 private Integer userId;
 private String userName;
 private String userPassword;

 public String getUserPassword() {
  return userPassword;
 }

 public void setUserPassword(String userPassword) {
  this.userPassword = userPassword;
 }

 public Integer getUserId() {
  return userId;
 }

 public void setUserId(Integer userId) {
  this.userId = userId;
 }

 public String getUserName() {
  return userName;
 }

 public void setUserName(String userName) {
  this.userName = userName;
 }

}
以及实体类的映射文件User.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="com.greysh.hibernate.User" table="USER" >
        <id name="userId" type="java.lang.Integer">
            <column name="USER_ID" />
            <generator class="native" />
        </id>
        <property name="userName" type="java.lang.String">
            <column name="USER_NAME"  />
        </property>
             <property name="userPassword" type="java.lang.String">
            <column name="USER_PASSWORD"  />
        </property>
    </class>
</hibernate-mapping>

User.java和User.hbm.xml要在同一个目录,并且ORM映射文件后缀必须为hbm.xml
不同类的一对一,一对多,多对多的关系也在此配置
如果对于性能要求很高的系统,
可以不指定一对一,一对多,多对多关系
而是把hibernate当ibatis去用,直接用hql或者sql
当然,对于性能要求极高的项目,则一般直接用servlet+jdbc+html

测试文件
package com.greysh.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;

public class Test {
 public static void main(String[] args) {
  User user = new User();
  user.setUserName("name");
  user.setUserPassword("pass");
  Configuration configuration = new Configuration();
  configuration.configure();
  SessionFactory sessionFactory = configuration.buildSessionFactory();
  Session session = sessionFactory.openSession();
  Transaction transaction = session.beginTransaction();
  transaction.begin();
  session.save(user);
  transaction.commit();
  session.close();
 }

}
Hibernate在执行的时候,首先
  Configuration configuration = new Configuration();
生成一个Configuration对象,然后用configure()进行编译
在 new Configuration()的时候会去寻找hibernate.properties加载配置
然而在编译的时候,如果没找到hibernate.properties,
则configure()会去寻找hibernate.cfg.xml文件
如果配置文件不是hibernate.properties或者是hibernate.cfg.xml文件
则需要指定配置文件的路径,configure(String resource)
由于 hibernate.cfg.xml的<mapping resource="com/greysh/hibernate/User.hbm.xml" />
会指定持久化文件的映射文件的路径,所以不需要调用
configuration.addClass(Class persistentClass)
去指定持久化类,但是properties配置需要
hibernate在持久化的时候默认会根据主键比较内存是否为同一个对象
但是可以重写hash和equals方法
然后接着用
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
创建一个Session工厂,打开一个session
Hibernate的Session和HTTP的Session完全没关系
打开Session后便开启一个事物
Hibernate有transient,persistent,detached三种状态
transient,detached没有纳入session的管理,persistent纳入了
persistent,detached在数据库有与之匹配的数据,transient没有
并且persistent在清理缓存(脏数据检查)的时候,会和数据库同步
然后
Transaction transaction = session.beginTransaction();
  transaction.begin();
打开事务.
并且调用 session的方法进行处理
比如session.save(user);
接着用 transaction.commit()提交事务
遇到异常可以用transaction.rollback()回滚
最后关闭session,释放资源
读者执行完这步后,会发现数据会新增一条数据,并且控制台会打印
Hibernate: insert into USER (USER_NAME, USER_PASSWORD) values (?, ?)
这个是hibernate底层调用的sql语句



发表于 Sun Functional 校园大使 [JavaEE] ( 四月 11, 2009 03:18 上午 ) Permalink | 评论[0]
评论:

发表一条评论:
  • HTML语法: 禁用