Hibernate Annotation案例分析

开发 后端
这里介绍Hibernate Annotation,目前,JPA(Java Persistence API)的使用范围越来越广,作为Java EE 5.0平台标准的ORM规范,得到了诸如:Hibernate、TopLink、OpenJpa等ORM框架的支持,同时还是EJB 3.0的重要组成部分。

Hibernate有很多值得学习的地方,这里我们以JPA——Hibernate Annotation一个案例来具体说明。

目前,JPA(Java Persistence API)的使用范围越来越广,作为Java EE 5.0平台标准的ORM规范,得到了诸如:Hibernate、TopLink、OpenJpa等ORM框架的支持,同时还是EJB 3.0的重要组成部分。JPA的宗旨是为POJO提供持久化标准规范。它能够脱离容器独立运行,方便开发和测试。本文将通过一个小实例来说明如何在Hibernate Annotation中使用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 Projec

点击"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中有一个地方需要改动,原来的写法是:

  1. private static Configuration configuration = new Configuration(); 

修改后为:

  1. private static AnnotationConfiguration configuration = new AnnotationConfiguration(); 

因为我们采用的是JPA注释方式来映射实体,另外AnnotationConfiguration这个类在hibernate-annotations.jar这个包中。

3、创建BaseDao

在com.ajax.core包下面新建BaseDao抽象类,里面定义的是持久化操作方法,有一点特别要注意,一定要在增加、删除、修改这几个方法中加入事务控制,不管是在BaseDao基类方法中加,还是在业务方法中加,一定要加事务控制,大象觉得在基类中加会比较好一点,这样做代码显得更少更简洁。如果不加事务控制,那么增、删、改这些操作都不会产生效果,因为默认情况下,它不会进行自动提交。在做这个例子的时候,这个问题曾经困扰了我好长时间。因此,请大家记住不要再犯和大象一样的错误!贴出部分代码,详情请看源码,里面有很全面的注释。

  1. /**  
  2.  * 抽象Dao类,用于持久化操作  
  3.  * @author 菠萝大象  
  4.  * @version 1.0  
  5.  */  
  6. public abstract class BaseDao<T> {  
  7.  
  8.     private static Log log = LogFactory.getLog(BaseDao.class);  
  9.       
  10.     /**  
  11.      * 获取Hibernate的Session对象  
  12.      */  
  13.     public Session getSession(){  
  14.         return HibernateSessionFactory.getSession();  
  15.     }  
  16.       
  17.     /**  
  18.      * 根据主键得到对象  
  19.      */  
  20.     public T getObject(Class clazz, Serializable id){  
  21.         return (T)getSession().get(clazz, id);  
  22.     }  
  23.       
  24.     /**  
  25.      * 保存对象  
  26.      */  
  27.     public void saveObject(T t) {  
  28.         Session session = getSession();  
  29.         Transaction tx = beginTransaction(session);  
  30.         try{  
  31.             session.saveOrUpdate(t);  
  32.             tx.commit();  
  33.         }catch(Exception e){  
  34.             tx.rollback();  
  35.             log.error("保存对象失败");  
  36.         }  
  37.     }  
  38.       
  39.     /**  
  40.      * 创建事务  
  41.      */  
  42.     private Transaction beginTransaction(Session session){  
  43.         return session.beginTransaction();  
  44.     }  

4、创建Employee

在com.ajax.employee.mode包下新建Employee类,这个就是POJO类,下面来详细说明里面的含义。

  1. @Entity  
  2. @Table(name = "EMPLOYEE")  
  3. public class Employee implements java.io.Serializable{  
  4.       
  5.     private Integer employee_id; //人员ID(主键)  
  6.     private String employee_name; //人员姓名  
  7.     private String sex; //性别  
  8.     private String birthday; //出生日期  
  9.     private String address; //地址  
  10.       
  11.     @Id  
  12.     @Column(name = "EMPLOYEE_ID")  
  13.     @TableGenerator(  
  14.          name="tab-store",  
  15.          table="GENERATOR_TABLE",  
  16.          pkColumnName = "G_KEY",  
  17.          pkColumnValue="EMPLOYEE_PK",  
  18.          valueColumnName = "G_VALUE",  
  19.          allocationSize=1 
  20.     )  
  21.     @GeneratedValue(strategy = GenerationType.TABLE,generator="tab-store")  
  22.     public Integer getEmployee_id() {  
  23.         return employee_id;  
  24.     }  
  25.     public void setEmployee_id(Integer employee_id) {  
  26.         this.employee_id = employee_id;  
  27.     }  

其它几个属性的getter和setter省略,这里我们要用到ejb3-persistence.jar,JPA的注解类就在这个包中,下面详细说明上面使用到的注解。
      @Entity:通过@Entity注解将一个类声明为一个实体bean
      @Table:通过 @Table注解可以为实体bean映射指定表,name属性表示实体所对应表的名称,如果没有定义 @Table,那么系统自动使用默认值:实体的类名(不带包名)
      @Id:用于标记属性的主键
      @Column:表示持久化属性所映射表中的字段,如果属性名与表中的字段名相同,则可以省略@Column注解,另外有两种方式标记,一是放在属性前,另一种是放在getter方法前,例如:

  1. @Column(name = "EMPLOYEE_NAME")  
  2. private String employee_name; 

 或者

  1. @Column(name = "EMPLOYEE_NAME")  
  2.     public String getEmployee_name() {  
  3.         return employee_name;  
  4.     } 

这两种方式都是正解的,根据个人喜好来选择。大象偏向于第二种,并且喜欢将属性名与字段名设成一样的,这样可以省掉@Column注解,使代码更简洁。
 @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”。

这里大象想说下,网上有很多文章写的是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脚本:

  1. CREATE TABLE EMPLOYEE(  
  2.     EMPLOYEE_ID int not null,  
  3.     EMPLOYEE_NAME varchar (20) null,  
  4.     SEX char (2) null,  
  5.     BIRTHDAY varchar(10) null,  
  6.     ADDRESS varchar(50) null,  
  7.     CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID)  
  8. )   
  9.  
  10. CREATE TABLE GENERATOR_TABLE(  
  11.     ID int not null,  
  12.     G_KEY varchar(20) null,  
  13.     G_VALUE int null,  
  14.     CONSTRAINT PK_GENERATOR_TABLE PRIMARY KEY (ID)   
  15. )  
  16.  
  17. INSERT INTO GENERATOR_TABLE VALUES(1,EMPLOYEE_PK,1) 

如果你觉得麻烦,不想建库及表,可以将后面的数据库下载下来,然后还原数据库就可以了。

6、修改hibernate.cfg.xml

本例中,采用的是JTDS连接驱动,我们要对配置文件作一些设置,另外还要加入POJO类。

  1. <property name="dialect">org.hibernate.dialect.SQLServerDialectproperty> 
  2.     <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driverproperty> 
  3.     <property name="connection.url">jdbc:jtds:sqlserver://localhost:1433/ajaxproperty> 
  4.     <property name="connection.username">saproperty> 
  5.     <property name="connection.password">自己密码(无密码就空着)property> 
  6.      
  7.     <mapping class="com.ajax.employee.model.Employee"/> 

以前没有使用JPA注解的时候,我们这里加入的都是hbm.xml文件,现在我们则加入的是类。

7、创建EmployeeManager

在com.ajax.employee.service下新建EmployeeManager类,这里面就是写业务方法,另外在这个类中添加一个main方法用于测试,将log4j的日志级别调整为DEBUG,这样我们就可以看到很详细的程序运行信息,源码中的注释很详细,这里就不贴出来了。
本例没有提供MySQL和Oracle数据库的脚本,不过这些应该很简单,按照最基本的方式建一个数据库和两张表就行了,这里附上两种数据库的hibernate配置。
MySQL:

  1. <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialectproperty> 
  2.     <property name="connection.driver_class">com.mysql.jdbc.Driverproperty> 
  3.     <property name="connection.url">jdbc:mysql://localhost:3306/ajaxproperty> 
  4.     <property name="connection.username">rootproperty> 
  5.     <property name="connection.password">自己的密码(无密码就空着)property> 

Oracle:

  1. <property name="hibernate.dialect">org.hibernate.dialect.OracleDialectproperty> 
  2.     <property name="connection.driver_class">oracle.jdbc.driver.OracleDriverproperty> 
  3.     <property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:自己的SIDproperty> 
  4.     <property name="connection.username">systemproperty> 
  5.     <property name="connection.password">自己的密码(无密码就空着)property> 

本文主要是从实用的角度来说明如何在Hibernate Annotation中使用JPA注释来简化开发,以及为后面的多种Ajax技术框架应用系列作一个前期准备。从这里可以看出,我们不需要再编写繁琐的hbm.xml文件。另外,JPA的功能很强大,这里只展示了其中的冰山一角,如果想深入学习JPA的话,请单独查找资料或购买相关书籍。

【编辑推荐】

  1. Hibernate查询缓存全面分析
  2. Hibernate经验简单描述
  3. Hibernate项目学习经验
  4. 概括Hibernate中cascade和inverse
  5. 3G与IPTV是发展大方向
责任编辑:仲衡 来源: blogjava
相关推荐

2009-09-22 17:32:38

Hibernate A

2009-09-25 17:26:55

使用Hibernate

2009-06-01 12:11:31

hibernatejpa复合主键

2009-09-23 16:39:51

Hibernate s

2009-09-22 14:46:18

struts-spri

2009-09-22 17:47:03

Hibernate s

2009-09-28 15:38:12

Hibernate P

2009-09-21 18:00:49

Hibernate X

2009-09-23 10:28:16

Hibernate映像

2009-09-23 13:33:51

Hibernate属性

2009-09-24 09:35:47

Hibernate插入

2009-09-22 14:23:37

Hibernate S

2017-05-12 15:47:15

Spring BootMybatis Ann Web

2009-09-21 14:24:08

Hibernate3.

2009-09-24 13:12:20

Hibernate原生

2009-09-24 13:49:31

Hibernate自增

2009-09-29 10:40:26

Hibernate业务

2009-09-22 11:24:07

Hibernate查询

2009-09-25 14:04:12

Hibernate读取

2009-06-18 14:51:12

Hibernate缓存Hibernate
点赞
收藏

51CTO技术栈公众号