第一个hibernate应用
1. 第一个类

建目录结构:
|- lib
...
|- src
|--|- road2hibernate
|- classes

第一个类:

package road2hibernate;

import java.util.Date;

public class Event {
private String title;
private Date date;
private Long id;

public Long getId() {
return id;
}

private void setId(Long id) {
this.id = id;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}
}


id 是 Event 的一个unique id,我们所有的持久化对象都需要这样一个id,
当我们建立hibernate 应用时,一个好的做法是使这个id 与应用逻辑相分离,这意味着我们在程序的任何地方都不要操作他,留给hibernate来做,这就是 setId 为 private 的原因
id 的类型我们使用了 Long, 而不是原始型,这样做会给我们省下不少麻烦,在应用中 id 要尽量使用对象型

2. 映射文件

我们已经有了类,需要告诉hibernate如何持久化他,这时映射文件就要上场了,他告诉hibernate把什么存入数据库以及如何存
Event 的映射文件应与Event 放在同一目录下,内容是这样的:


Event.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=
"de.gloegl.road2hibernate.Event" table="EVENTS">
<id name=
"id" column="uid" type="long">
<generator class=
"increment"/>
</id>
<property name=
"date" type="timestamp"/>
<property name=
"title" column="eventtitle"/>
</class>

</hibernate-mapping>


在两个hibernate-mapping 标签间包含一个 class 元素,来声明这个映射文件涉及到哪个类,和这个类与数据库中的哪个表对应(Event类与EVENTS表映射)
接下来给hibernate指定一个唯一的标识符id, 我们不必怎么操作这个id, 只需告诉hibernate 如何生成这个id
id 元素是类中id 属性的声明,name="id" 是说属性的名字,column属性指明 EVENTS表中哪一列对应这个id
property 元素告诉hibernate使用哪个 get- set-
title-property 有一个 column属性,而 date-property没有,在没指定column属性时,hibernate会自动用property-name 做列名
title-property 没有 type属性,hibernate回自动匹配正确的类型,但date型的除外,timestamp/time, 所以 date-property指定了 type属性

3. 配置数据库


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>

<!-- Database connection settings -->
<property name=
"connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name=
"connection.url">jdbc:mysql://localhost/javatest</property>
<property name=
"connection.username">javauser</property>
<property name=
"connection.password">javadude</property>

<!-- JDBC connection pool (use the built-in) -->
<property name=
"connection.pool_size">1</property>

<!-- SQL dialect -->
<property name=
"dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- Echo all executed SQL to stdout -->
<property name=
"show_sql">true</property>

<mapping resource=
"Event.hbm.xml"/>

</session-factory>

</hibernate-configuration>



dialect-property 指定所使用数据库的方言,这样hibernate可以更好的与数据库沟通
下面还指定了用JDBC Connection 做事务和一个简单的cache

现在的目录结构是这样:
|- lib
...
|- src
|--|- road2hibernate
|- classes
|--|- hibernate.cfg.xml
|--|- Event.hbm.xml


4. 编写业务逻辑

现在先写一个简单的类启动hibernate, 像这样:

package road2hibernate;

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

public class EventManager {

public static void main(String[] args) {
Session s = HibernateUtil.currentSession();
HibernateUtil.closeSession();
System.exit(0);
}

}


这个类用了一个叫HibernateUtil 的类来获得 Session实例,HibernateUtil用"ThreadLocal Session Pattern"把当前的session 与当前线程联系起来
HibernateUtil像这样:

package road2hibernate;

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {

private static final SessionFactory sessionFactory;

static {
try {
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println(
"Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static final ThreadLocal session = new ThreadLocal();

public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}

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


HibernateUtil 在静态初始化块中创建SessionFactory,用两个静态方法获得和关闭session, 用ThreadLocal变量来持有session
通过ThreadLocal存储的数据总与当前线程相关,JVM为每个运行的线程都绑定了私有的本地实例存储空间,为多线程环境的并发问题提供了隔离机制
sessionFactory创建Session,sessionFactory是线程安全的,但Session 不是,所以使用ThreadLocal。
ThreadLocal为每个线程维护一个私有的变量空间,实际就是在JVM中维护一个Map, key 就是当前的线程对象,value 就是通过ThreadLocal.set 保存的对象实例,当用ThreadLocal.get 时会根据当前线程对象的引用,取回Map中对应的对象

Configuration 类负责管理Hibernate 的配置信息,Hibernate 运行时需要获得一些基本的信息,包括:
(1)数据库URL
(2)数据库用户名
(3)数据库密码
(4)JDBC驱动类
(5)数据库dialect, 用于对特定数据库提供支持
当我们调用:
new Configuration().configure();时Hibernate 会自动在CLASSPATH中搜寻hibernate.cfg.xml 将其读取到内存中作为后续操作的基本配置

SessionFactory 负责创建 Session实例,通过Configuration实例创建

Session 是持久层操作的基础,相当于JDBC中的Connection, 通过SessionFactory 实例创建

下面往数据库中插入一条记录,现在EventManager 像这样:

package road2hibernate;

import org.hibernate.*;
import org.hibernate.cfg.*;
import java.util.Date;

public class EventManager {

public static void main(String[] args) {
EventManager em = new EventManager();
Session s = HibernateUtil.currentSession();

String title =
"hbm";
Date theDate = new Date();
em.store( title, theDate );

HibernateUtil.closeSession();
System.exit(0);
}

private void store(String title, Date theDate) {
try {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();

Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);

session.save(theEvent);

tx.commit();
HibernateUtil.closeSession();
} catch (HibernateException e) {
e.printStackTrace();
}
}

}


现在的目录结构是这样:
|- lib
...
|- src
|--|- road2hibernate
|--|--|- Event.java
|--|--|- EventManager.java
|--|--|- HibernateUtil.java
|- classes
|--|- hibernate.cfg.xml
|--|- Event.hbm.xml

编写build.xml

<project name=
"hbmapp" basedir=".">
<property name=
"src.home" value="${basedir}/src"/>
<property name=
"classes.home" value="${basedir}/classes"/>
<property name=
"lib.home" value="${basedir}/lib"/>

<!--
"compile" target -->
<target name=
"compile">
<javac srcdir=
"${src.home}" destdir="${classes.home}" debug="on">
<classpath>
<fileset dir=
"${lib.home}">
<include name=
"*.jar"/>
</fileset>
</classpath>
</javac>
</target>

<!--
"run" target -->
<target name=
"run">
<java classname=
"road2hibernate.EventManager" classpath="${classes.home}">
<classpath>
<fileset dir=
"${lib.home}">
<include name=
"*.jar"/>
</fileset>
</classpath>
</java>
</target>

</project>


5. 运行

在命令行: ant compile
然后: ant run
现在查询数据库就可以看到刚刚插入的记录了
irini   2005-12-28 22:35:01 评论:0   阅读:460   引用:0

发表评论>>

署名发表(评论可管理,不必输入下面的姓名)

姓名:

主题:

内容: 最少15个,最长1000个字符

验证码: (如不清楚,请刷新)

Copyright@2008 powered by YuLog