目前, JPA ( Java Persistence API )的使用范围越来越广,作为 Java EE 5.0 平台标准的 ORM 规范,得到了诸如: Hibernate 、 TopLink 、 OpenJpa 等 ORM 框架的支持,同时还是 EJB 3.0 的重要组成部分。 JPA 的宗旨是为 POJO 提供持久化标准规范。它能够脱离容器独立运行,方便开发和测试。本文将通过一个小实例来说明如何在 Hibernate 中使用 JPA ,来达到简化编程的目的。
开发环境 Eclipse 3.3.1 MyEclipse 6.0.1GA Tomcat 6.10 SQL Server 2000
hibernate-3.2.5.GA hibernate-annotations-3.3.0.GA
ejb3-persistence hibernate-commons-annotations-3.0.0.GA
本文是为后续的多种 Ajax 技术框架应用系列作一个前期准备,让大家先了解一下相比与以前的 Hibernate ORM 映射的不同之处,以及采用 JPA 所带来的好处。
为了保证程序能顺序运行,避免不同的 Eclipse 版本之间产生错误,大象强烈建议,下载源码后,按源码中的工程名,自己单独新建同一个工程,再将 src 和 WEB-INF/lib 目录下的所有文件 COPY 至对应的目录下。
1、创建 Web Project
点击"File"- > "New" ,选择"Web Project" ,在"Project Name" 中输入ajax ,点击"Finish" 。下载本文后面需要用到的JAR 包,加入到WEB-INF/lib 目录下,在ajax 工程中,文本采用的是UTF-8 编码。
2、创建 HibernateSessionFactory
传统的方法就是在工程名上点右键,选择 ”MyEclipse” - >”Add Hibernate Capabilities” ,然后就是按照提示一步一步做,不过在MyEclipse 6.0.1 中添加Hibernate 还是只能支持3.1 ,除非你选择 ” Add Spring Capabilities” ,里面才有 Hibernate 3.2 的类库,要想完全兼容 JPA ,必须采用 3.2 以上版本。
这里大家直接使用源码中的 HibernateSessionFactory ,注意请先建包:com.ajax.core. HibernateSessionFactory 中有一个地方需要改动,原来的写法是:
private static Configuration configuration = new Configuration(); 修改后为:
private static AnnotationConfiguration configuration = new AnnotationConfiguration(); 因为我们采用的是 JPA 注释方式来映射实体,另外 AnnotationConfiguration 这个类在 hibernate-annotations.jar 这个包中。
3、创建 BaseDao
在 com.ajax.core 包下面新建 BaseDao 抽象类,里面定义的是持久化操作方法,有一点特别要注意,一定要在增加、删除、修改这几个方法中加入事务控制,不管是在 BaseDao 基类方法中加,还是在业务方法中加,一定要加事务控制,大象觉得在基类中加会比较好一点,这样做代码显得更少更简洁。如果不加事务控制,那么增、删、改这些操作都不会产生效果,因为默认情况下,它不会进行自动提交。在做这个例子 的时候,这个问题曾经困扰了我好长时间。因此,请大家记住不要再犯和大象一样的错误!贴出部分代码,详情请看源码,里面有很全面的注释。
/**
* 抽象Dao类,用于持久化操作
* @author 菠萝大象
* @version 1.0
*/
public abstract class BaseDao < T > {
private static Log log = LogFactory.getLog(BaseDao. class );
/**
* 获取Hibernate的Session对象
*/
public Session getSession(){
return HibernateSessionFactory.getSession();
}
/**
* 根据主键得到对象
*/
public T getObject(Class clazz, Serializable id){
return (T)getSession().get(clazz, id);
}
/**
* 保存对象
*/
public void saveObject(T t) {
Session session = getSession();
Transaction tx = beginTransaction(session);
try {
session.saveOrUpdate(t);
tx.commit();
} catch (Exception e){
tx.rollback();
log.error( "保存对象失败" );
}
}
/**
* 创建事务
*/
private Transaction beginTransaction(Session session){
return session.beginTransaction();
}
} 4、创建 Employee 中国网管论坛bbs.bitsCN.com
在 com.ajax.employee.mode 包下新建 Employee 类,这个就是 POJO 类,下面来详细说明里面的含义。
@Entity
@Table (name = "EMPLOYEE" )
public class Employee implements java.io.Serializable{
private Integer employee_id; // 人员ID(主键)
private String employee_name; // 人员姓名
private String sex; // 性别
private String birthday; // 出生日期
private String address; // 地址
@Id
@Column (name = "EMPLOYEE_ID" )
@TableGenerator (
name = "tab-store" , 网管联盟www.bitsCN.com
table = "GENERATOR_TABLE" ,
pkColumnName = "G_KEY" ,
pkColumnValue = "EMPLOYEE_PK" ,
valueColumnName = "G_VALUE" , 中国网管联盟www.bitscn.com
allocationSize = 1
)
@GeneratedValue (strategy = GenerationType.TABLE ,generator = "tab-store" )
public Integer getEmployee_id() {
return employee_id;
}
public void setEmployee_id(Integer employee_id) {
this .employee_id = employee_id;
}
} 其它几个属性的 getter 和 setter 省略,这里我们要用到 ejb3-persistence.jar,JPA 的注解类就在这个包中,下面详细说明上面使用到的注解。
@Entity : 通过 @Entity 注解将一个类声明为一个实体 bean
@Table : 通过 @Table 注解可以为实体 bean 映射指定表, name 属性表示实体所对应表的名称 ,如果没有定义 @Table ,那么系统自动使用默认值:实体的类名(不带包名)
@Id : 用于标记属性的主键
@Column : 表示持久化属性所映射表中的字段,如果属性名与表中的字段名相同,则可以省略 @Column 注解,另外有两种方式标记,一是放在属性前,另一种是放在 getter 方法前,例如:
@Column(name = " EMPLOYEE_NAME " )
private String employee_name; 或者
@Column(name = " EMPLOYEE_NAME " ) 网管网bitsCN_com
public String getEmployee_name() {
return employee_name;
} 这两种方式都是正解的,根据个人喜好来选择。大象偏向于第二种,并且喜欢将属性名与字段名设成一样的,这样可以省掉 @Column 注解,使代码更简洁。 网管网bitsCN.com
@TableGenerator : 表生成器, 将当前主键的值单独保存到一个数据库表中,主键的值每次都是从指定的表中查询来获得,这种生成主键的方式是很常用的。这种方法生成主键的策略可以适用于任何数据库,不必担心不同数据库不兼容造成的问题。大象推荐这种方式管理主键,很方便,集中式管理表的主键,而且更换数据库不会造成很大的问题。各属性含义如下:
name : 表示该表主键生成策略的名称,这个名字可以自定义,它被引用在 @GeneratedValue 中设置的" generator" 值中
table : 表示表生成策略所持久化的表名,说简单点就是一个管理其它表主键的表,本例中,这个表名为 GENERATOR_TABLE
pkColumnName : 表生成器中的列名,用来存放其它表的主键键名,这个列名是与表中的字段对应的
pkColumnValue : 实体表所对应到生成器表中的主键名,这个键名是可以自定义滴
valueColumnName : 表生成器中的列名,实体表主键的下一个值,假设 EMPLOYEE 表中的 EMPLOYEE_ID 最大为 2 ,那么此时,生成器表中与实体表主键对应的键名值则为 3
allocationSize : 表示每次主键值增加的大小,例如设置成 1 ,则表示每次创建新记录后自动加 1 ,默认为 50
@GeneratedValue : 定义主键生成策略,这里因为使用的是 TableGenerator ,所以,主键的生成策略为 GenerationType.TABLE , 生成主键策略的名称则为前面定义的 ” tab-store ” 。 网管网bitsCN_com
这里大象想说下,网上有很多文章写的是 strategy = GenerationType.AUTO 或是 strategy = GenerationType. SEQUENCE ,采用 SEQUENCE 序列是因为 Oracle 数据中不支持 identity 自动增长,要想使用它,还得在数据库中创建一个序列,如果要更换数据库,那将是一个非常麻烦的事情。 SEQUENCE 生成方式我们暂且不谈,这里说下采用 AUTO 和 IDENTITY 的生成方式,本例采用的是 SQL Server 2000 作为数据库,所以如果想使用 AUTO 或是 IDENTITY 生成策略,则一定要对主键加上 identity 标识,如 identity(1,1) 。不过对于 AUTO 来说,是根据不同的数据库选择最合适的自增主键生成策略。如果使用 MySQL ,则主键要定义 AUTO_INCREMENT ,如果是 Oracle ,则要 创建 Sequence 来实现自增。不管采用何种生成策略,增、删、改这些方法中一定要加入事务,否则数据是不会添加到数据库中滴~~~这是大象反复测试过的结果!
5、创建数据库及表
接下来,我们需要为本例创建一个数据库及必要的表。数据库名为 ajax ,表只有两个 EMPLOYEE 和 GENERATOR_TABLE ,下面是 SQL 脚本: 中国网管论坛bbs.bitsCN.com
CREATE TABLE EMPLOYEE(
EMPLOYEE_ID int not null ,
EMPLOYEE_NAME varchar ( 20 ) null ,
SEX char ( 2 ) null ,
BIRTHDAY varchar ( 10 ) null ,
ADDRESS varchar ( 50 ) null , 中国网管联盟www、bitsCN、com
CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID)
)
CREATE TABLE GENERATOR_TABLE(
ID int not null ,
G_KEY varchar ( 20 ) null ,
G_VALUE int null ,
CONSTRAINT PK_GENERATOR_TABLE PRIMARY KEY (ID) 网管联盟www.bitsCN.com
)
INSERT INTO GENERATOR_TABLE VALUES ( 1 ,EMPLOYEE_PK, 1 ) 如果你觉得麻烦,不想建库及表,可以将后面的数据库下载下来,然后还原数据库就可以了。
6、修改 hibernate.cfg.xml
本例中,采用的是 JTDS 连接驱动,我们要对配置文件作一些设置,另外还要加入 POJO 类。
< property name ="dialect" > org.hibernate.dialect.SQLServerDialect </ property >
< property name ="connection.driver_class" > net.sourceforge.jtds.jdbc.Driver </ property >
< property name ="connection.url" > jdbc:jtds:sqlserver://localhost:1433/ajax </ property >
< property name ="connection.username" > sa </ property >
< property name ="connection.password" > 自己密码(无密码就空着) </ property >
<!-- 实体类 -->
< mapping class ="com.ajax.employee.model.Employee" /> 以前没有使用 JPA 注解的时候,我们这里加入的都是 hbm.xml 文件,现在我们则加入的是类。
7、创建 EmployeeManager
在 com.ajax.employee.service 下新建 EmployeeManager 类,这里面就是写业务方法,另外在这个类中添加一个 main 方法用于测试,将 log4j 的日志级别调整为 DEBUG ,这样我们就可以看到很详细的程序运行信息,源码中的注释很详细,这里就不贴出来了。 中国网管联盟www、bitsCN、com
本例没有提供 MySQL 和 Oracle 数据库的脚本,不过这些应该很简单,按照最基本的方式建一个数据库和两张表就行了,这里附上两种数据库的 hibernate 配置。
MySQL:
< property name ="hibernate.dialect" > org.hibernate.dialect.MySQLInnoDBDialect </ property >
< property name ="connection.driver_class" > com.mysql.jdbc.Driver </ property >
< property name ="connection.url" > jdbc:mysql://localhost:3306/ajax </ property >
< property name ="connection.username" > root </ property >
< property name ="connection.password" > 自己的密码(无密码就空着) </ property > Oracle:
< property name ="hibernate.dialect" > org.hibernate.dialect.OracleDialect </ property >
< property name ="connection.driver_class" > oracle.jdbc.driver.OracleDriver </ property >
< property name ="connection.url" > jdbc:oracle:thin:@127.0.0.1:1521:自己的SID </ property > 中国网管联盟www、bitsCN、com
< property name ="connection.username" > system </ property >
< property name ="connection.password" > 自己的密码(无密码就空着) </ property > 本文主要是从实用的角度来说明如何在 Hibernate 中使用 JPA 注释来简化开发,以及为后面的 多种 Ajax 技术框架应用系列作一个前期准备。 从这里可以看出,我们不需要再编写繁琐的 hbm.xml 文件。另外, JPA 的功能很强大,这里只展示了其中的冰山一角,如果想深入学习 JPA 的话,请单独查找资料或购买相关书籍。
下面是本例中必须的JAR包
点击下载:antlr-2.7.6 asm-1.5.3 cglib-2.1.3 commons-collections-2.1.1 commons-lang-2.1
commons-logging-1.0.4 log4j-1.2.14 ehcache-1.2.3 ejb3-persistence-3.0
hibernate3-3.2.5 hibernate-annotations-3.3.0 hibernate-commons-annotations-3.0.0
mysql-connector .jar jtds.jar classes12.jar
点击下载:ajax_project db_ajax
本文为菠萝大象原创,如要转载请注明出处。