学习JPA——Hibernate Annotation使用实例

    目前,JPAJava Persistence API)的使用范围越来越广,作为Java EE 5.0平台标准的ORM规范,得到了诸如:HibernateTopLinkOpenJpaORM框架的支持,同时还是EJB 3.0的重要组成部分。JPA的宗旨是为POJO提供持久化标准规范。它能够脱离容器独立运行,方便开发和测试。本文将通过一个小实例来说明如何在Hibernate中使用JPA,来达到简化编程的目的。
    本文是让大家了解一下相比与以前的Hibernate ORM映射的不同之处,以及采用JPA所带来的好处。
    为了保证程序能顺序运行,避免不同的Eclipse版本之间产生错误,强烈建议大家按源码中的工程名,自己单独新建同一个工程,再将srcWEB-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 thj
 * @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
       在com.ajax.employee.mode包下新建Employee类,这个就是POJO类,下面来详细说明里面的含义。

@Entity
@Table(name 
= "EMPLOYEE")
@org.hibernate.annotations.Entity(dynamicUpdate=true,dynamicInsert=true)//在插入数据的时候,数据表里的默认值有效,不加此行则无效

@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)//应用缓存策略
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",
         table
="GENERATOR_TABLE",
         pkColumnName 
= "G_KEY",
         pkColumnValue
="EMPLOYEE_PK",
         valueColumnName 
= "G_VALUE",
         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;
    }

}

       其它几个属性的gettersetter省略,这里我们要用到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 " )
    
public  String getEmployee_name() {
        
return  employee_name;
    }
       这两种方式都是正解的,根据个人喜好来选择。本人偏向于第二种,并且喜欢将属性名与字段名设成一样的,这样可以省掉 @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 脚本:

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 ,
    
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) 
)

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 ,这样我们就可以看到很详细的程序运行信息,源码中的注释很详细,这里就不贴出来了。
    本文 主要是从实用的角度来说明如何在 Hibernate 中使用 JPA 注释来简化开发 从这里可以看出,我们不需要再编写繁琐的 hbm.xml 文件。另外, JPA 的功能很强大,这里只展示了其中的冰山一角,如果想深入学习 JPA 的话,请单独查找资料或购买相关书籍。

你可能感兴趣的:(Hibernate,annotation,jpa)