??目前,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
????本文是让大家了解一下相比与以前的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中有一个地方需要改动,原来的写法是:
????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();
????}
}
???????在com.ajax.employee.mode包下新建Employee类,这个就是POJO类,下面来详细说明里面的含义。
@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",
?????????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;
????}
}
??????@Entity:通过@Entity注解将一个类声明为一个实体bean
??????@Table:通过 @Table注解可以为实体bean映射指定表,name属性表示实体所对应表的名称,如果没有定义 @Table,那么系统自动使用默认值:实体的类名(不带包名)
??????@Id:用于标记属性的主键
??????@Column:表示持久化属性所映射表中的字段,如果属性名与表中的字段名相同,则可以省略@Column注解,另外有两种方式标记,一是放在属性前,另一种是放在getter方法前,例如:
????private?String?employee_name;
????public?String?getEmployee_name()?{
????????return?employee_name;
????}
??????@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脚本:
????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="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"/>
????7、创建EmployeeManager
???????在com.ajax.employee.service下新建EmployeeManager类,这里面就是写业务方法,另外在这个类中添加一个main方法用于测试,将log4j的日志级别调整为DEBUG,这样我们就可以看到很详细的程序运行信息,源码中的注释很详细,这里就不贴出来了。
????本例没有提供MySQL和Oracle数据库的脚本,不过这些应该很简单,按照最基本的方式建一个数据库和两张表就行了,这里附上两种数据库的hibernate配置。
????MySQL:
????<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>
????<property?name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
????<property?name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:自己的SID</property>
????<property?name="connection.username">system</property>
????<property?name="connection.password">自己的密码(无密码就空着)</property>
????下面是本例中必须的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
????本文为菠萝大象原创,如要转载请注明出处。
详细解决方案
学习JPA――Hibernate Annotation施用实例
热度:372 发布时间:2012-08-22 09:50:35.0
????private?static?Configuration?configuration?=?new?Configuration();
???????修改后为:
????private?static?AnnotationConfiguration?configuration?=?new?AnnotationConfiguration();
???????因为我们采用的是JPA注释方式来映射实体,另外AnnotationConfiguration这个类在hibernate-annotations.jar这个包中。
/**
????4、创建Employee
@Entity
???????其它几个属性的getter和setter省略,这里我们要用到ejb3-persistence.jar,JPA的注解类就在这个包中,下面详细说明上面使用到的注解。
????@Column(name?=?"EMPLOYEE_NAME")
???????或者
????@Column(name?=?"EMPLOYEE_NAME")
???????这两种方式都是正解的,根据个人喜好来选择。大象偏向于第二种,并且喜欢将属性名与字段名设成一样的,这样可以省掉@Column注解,使代码更简洁。
CREATE?TABLE?EMPLOYEE(
???????如果你觉得麻烦,不想建库及表,可以将后面的数据库下载下来,然后还原数据库就可以了。
????<property?name="dialect">org.hibernate.dialect.SQLServerDialect</property>
???????以前没有使用JPA注解的时候,我们这里加入的都是hbm.xml文件,现在我们则加入的是类。
????<property?name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
????Oracle:
????<property?name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
????本文主要是从实用的角度来说明如何在Hibernate中使用JPA注释来简化开发。从这里可以看出,我们不需要再编写繁琐的hbm.xml文件。另外,JPA的功能很强大,这里只展示了其中的冰山一角,如果想深入学习JPA的话,请单独查找资料或购买相关书籍。 相关解决方案
- hibernate 存入数据库当前时间
- Hibernate 投射文件中length属性无法改变integer字段的默认长度
- Exception in thread "main" org.hibernate.HibernateException: /hibernate.cfg.xml解决办法
- hibernate DAO中加了局物,未提交
- hibernate 字段lazy 的兑现原理
- Hibernate 的query.list()的有关问题
- 多对多双向联系关系(annotation&xml)
- Hibernate 关联表字段赋值有关问题
- 零配置的有关问题(struts2+Hibernate)
- 一对多(多对一)双向联系关系(annotation&xml)
- hibernate 连接 oracle session 有关问题
- hibernate 中没有做一对多 , 那种关联映射的关联的话如何做连接查询
- hibernate 联接mysql出错
- 大神们开始觅错啦!org.hibernate.exception.SQLGrammarException: could not execute query
- struts2,hibernate,spring3 常用框架的API CHM版本,该怎么处理
- struts2,hibernate,spring3 惯用框架的API CHM版本
- struts hibernate 测试小例子 不报错 但数据库没反应 求分析项目在小弟我的资源里面
- struts2 hibernate 分页有关问题
- hibernate与此同时使用多数据源?spring+hibernate
- hibernate 保留对象时,根据映射文件,无法获取主键值
- hibernate 多对多添加有关问题,弄一天多了,请求大佬解答。小的 在此谢过了
- struts + hibernate 后台页面修改数据后,前台页面显示的内容新旧数据交替出现。请高手帮忙分析上原因
- hibernate 多对1关联配置有关问题
- Hibernate,级联保存为何无效?
- hibernate 一对1 ,插入不进去数据
- hibernate 连接oracle异常
- struts+spring+hibernate 开发,在action层调用service层接口,结果替null 注入失败,需高手帮忙
- Hibernate 映射有关问题
- SSH框架导入struts,hibernate,spring分先后顺序吗>>解决方法
- Hibernate 中的session怎么管理