跟我学OpenJPA

http://www.iteye.com/topic/1122411

本章是基础开发环境配置,不需要请绕行跟我学OpenJPA之二(Hello OpenJPA)

 

 

受jinnianshilongnian的委托要我写个《跟我学JPA》的系列,但是JPA方面确实研究不深,平时工作太多,也无心去研究那些深奥的源码和理论,大多做的都是一些实际的工作。所以力所能及,简单写个《跟我学OpenJPA》,希望更多的人和我一起使用OpenJPA。

 

以前一直没有写过系列的文章,本来没有什么思路,但是开头的时候突然想到了一句话“工欲善其事,必先利其器”,那么今天我们就从这里开始,“器”!

 

此器称之为Eclipse,此器凶名之大以至于Sun如其名一般,被O一口吃掉。因此江湖中各种版本无数,以My系老大为主,MyEclipse是目前培训中心必备之利器也,可惜My老大水土不服,闹了会肚子之后居然把我等墙之。想当初为了其硕大无比的身材,中海、电信、铁通轮番上阵可惜依然无法越过那高高的围墙,第一次碰到了被别人墙的滋味。最后不得已转向原汁原味的Eclipse后发现“原装的才是最好的”!


==================GTK 下Eclipse紧凑布局的分割线==============

每次我贴Eclipse的截图有人问这个问题,那么有此问题的请参见我之前的文章Ubuntu下Eclipse紧凑布局修改方法

 

=====================开工的分割线==================

外事问谷哥,输入Eclipse后直奔Download而去,问度娘者请注意屏蔽各类广告。记得是下载Eclipse IDE for Java EE Developers。下载后给JDK安好家,安排好eclipse.ini的内容,就可以直奔主题了。下面是我的布局,因为用到了GIT、GWT调试,界面略显复杂。


下面给Eclipse配上各大杀器:

 

一、Maven(M2E)

我个人的经验,安装这个两个都差不多。反正我只准备用maven做库的管理,编译还是让Eclipse去搞定吧。

 

 

二、Properties Editor(小日本也能出好东西)

这个是一直用的东西,比其他此类插件包括自带的都要好用。

 

 

三、EditorList

这个插件也是我必备之一,可惜作者没有升级,我是用他的源码用新的Eclipse编译了一个jar出来EditorList_1.0.7.jar ,直接放入plugins目录即可,记得--clean

 

 

http://www.iteye.com/topic/1122417

Hello World、Hello Delphi、Hello ASP、Hello Java、Hello SSH,这些都是我经历过的Hello,今天大家陪我再一次经历Hello OpenJPA。。。。

 

一、新建一个普通的Java项目(不是WTP项目)


 

二、转换为Maven项目

 

增加一些库依赖,pom.xml代码如下:

Xml代码

因为pom.xml中没有配置src的未知,所以默认转换为maven项目之后,build path中的source中会变为空,这个时候要吧src重新增加进去,最简单的方法就是直接加!


 

三、增加slf4j记录日志

在src中新建一个log4j.properties文件,修改内容如下:

Cpp代码
# This is the configuring for logging displayed in the Application Server
log4j.rootCategory=INFO, stdout

#stdout configure
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-d{HH:mm:ss}-%p]%m%n

 

四、转换为JPA项目

首先在Data Source Explorer中增加对应的数据库,Drivers没有请自己设置


 

然后右键项目,将其转换为JPA的项目


因为Eclipse没有直接支持OpenJPA,所以这里直接选择Generic2.0

 

完成后,Eclipse会自动在src中新建META-INF目录,在META-INF中新建persistence.xml文件,自动生成的大多不能用,结合OpenJPA的配置方法修改内容如下:

Xml代码

这些配置的参数在OpenJPA的文档中都有,因为没有找到中文的文档,大家有需要的话直接去看官方文档吧。其中有一个地方需要解释的,javax.persistence.jdbc.driver等等这些参数是JPA标准,OpenJPA中也有类似的参数,一般情况下建议大家还是直接使用标准参数来配置

 

五、生成Entities From Tables

转换为JPA项目之后,Eclipse就能够使用JPA Tools进行JPA的管理,尤其是Entities From Tables非常好用(虽然我重来不用 ^_^)。

右键项目,选择JPA Tools进行操作,我们先把数据库中的t_xx表转换出来


 

剩下的操作,大家就按照步骤来吧,因为演示的t_xx没有任何外键,所以按照最简单的方式转出来就可以。有可能自动生成后这个class会报错,这个时因为Eclipse诶有把TXx定义到persistence.xml中,如果报错大家就手工添加进去,下载的源码包内我已经手工修改过。

但是自动化生成的东西并不非常合适,至少在以后的通过Entities生成Tables的时候就存在很多的问题,因此我一般都用自己的做的一个转换工具进行代码自动生成。

com.strong.module.txx.jpa.TXx

Java代码
package com.strong.module.txx.jpa;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * TXx entity
 * 
 * @author Simen 自动生成时间: 2011-10-02 08:31:29
 */

@Entity
@Table(name = "t_xx")
public class TXx implements java.io.Serializable {

  /**
   * 
   */
  private static final long serialVersionUID = 1L;

  public static final String S_XXID = "xx_id"; // PRIMARY
  public static final String S_XXBZ = "xx_bz"; // 选项备注
  public static final String S_XXDM = "xx_dm"; // 选项代码
  public static final String S_XXLX = "xx_lx"; // 选项类型
  public static final String S_XXMC = "xx_mc"; // 选项名称
  public static final String S_XXXH = "xx_xh"; // 选项序号 在同一分类中的顺序号
  public static final String S_XXBY1 = "xx_by1"; // 备用1
  public static final String S_XXBY2 = "xx_by2"; // 备用2
  public static final String S_XXBY3 = "xx_by3"; // 备用3
  public static final String S_XXBY4 = "xx_by4"; // 备用4
  public static final String S_XXBY5 = "xx_by5"; // 备用5
  public static final String S_XXBY6 = "xx_by6"; // 备用6
  public static final String S_XXBY7 = "xx_by7"; // 备用7
  public static final String S_XXBY8 = "xx_by8"; // 备用8

  // Fields
  private Integer xxId; // PRIMARY
  private String xxBz; // 选项备注
  private String xxDm; // 选项代码
  private String xxLx; // 选项类型
  private String xxMc; // 选项名称
  private Integer xxXh; // 选项序号 在同一分类中的顺序号
  private String xxBy1; // 备用1
  private String xxBy2; // 备用2
  private String xxBy3; // 备用3
  private Integer xxBy4; // 备用4
  private Integer xxBy5; // 备用5
  private Date xxBy6; // 备用6
  private Date xxBy7; // 备用7
  private Float xxBy8; // 备用8

  public TXx() {

  }

  // Constructors

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "AuthorSeqXX")
  @SequenceGenerator(name = "AuthorSeqXX", allocationSize = 1)
  @Column(name = "xx_id", unique = true, nullable = false, insertable = true, updatable = true)
  public Integer getXxId() {
    return xxId;
  }

  public void setXxId(Integer xxId) {
    this.xxId = xxId;
  }

  @Column(name = "xx_bz", length = 255)
  public String getXxBz() {
    return xxBz;
  }

  public void setXxBz(String xxBz) {
    this.xxBz = xxBz;
  }

  @Column(name = "xx_dm", length = 255)
  public String getXxDm() {
    return xxDm;
  }

  public void setXxDm(String xxDm) {
    this.xxDm = xxDm;
  }

  @Column(name = "xx_lx", length = 255)
  public String getXxLx() {
    return xxLx;
  }

  public void setXxLx(String xxLx) {
    this.xxLx = xxLx;
  }

  @Column(name = "xx_mc", length = 255)
  public String getXxMc() {
    return xxMc;
  }

  public void setXxMc(String xxMc) {
    this.xxMc = xxMc;
  }

  @Column(name = "xx_xh", length = 10)
  public Integer getXxXh() {
    return xxXh;
  }

  public void setXxXh(Integer xxXh) {
    this.xxXh = xxXh;
  }

  @Column(name = "xx_by1", length = 255)
  public String getXxBy1() {
    return xxBy1;
  }

  public void setXxBy1(String xxBy1) {
    this.xxBy1 = xxBy1;
  }

  @Column(name = "xx_by2", length = 255)
  public String getXxBy2() {
    return xxBy2;
  }

  public void setXxBy2(String xxBy2) {
    this.xxBy2 = xxBy2;
  }

  @Column(name = "xx_by3", length = 255)
  public String getXxBy3() {
    return xxBy3;
  }

  public void setXxBy3(String xxBy3) {
    this.xxBy3 = xxBy3;
  }

  @Column(name = "xx_by4", length = 10)
  public Integer getXxBy4() {
    return xxBy4;
  }

  public void setXxBy4(Integer xxBy4) {
    this.xxBy4 = xxBy4;
  }

  @Column(name = "xx_by5", length = 10)
  public Integer getXxBy5() {
    return xxBy5;
  }

  public void setXxBy5(Integer xxBy5) {
    this.xxBy5 = xxBy5;
  }

  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "xx_by6", length = 19)
  public Date getXxBy6() {
    return xxBy6;
  }

  public void setXxBy6(Date xxBy6) {
    this.xxBy6 = xxBy6;
  }

  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "xx_by7", length = 19)
  public Date getXxBy7() {
    return xxBy7;
  }

  public void setXxBy7(Date xxBy7) {
    this.xxBy7 = xxBy7;
  }

  @Column(name = "xx_by8", length = 12)
  public Float getXxBy8() {
    return xxBy8;
  }

  public void setXxBy8(Float xxBy8) {
    this.xxBy8 = xxBy8;
  }

}

 

com.strong.module.txx.jpa.TXx_ 这个类比较奇特,是JPA规范中定义个一个特殊类,主要的作用是构造查询,这个以后再说

Java代码
package com.strong.module.txx.jpa;

import java.util.Date;

import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

/**
 * TXx_ entity
 * 
 * @author Simen 自动生成时间: 2011-10-02 08:31:29
 */

@StaticMetamodel(TXx.class)
public abstract class TXx_ {

  public static volatile SingularAttribute<TXx, Integer> xxId;
  public static volatile SingularAttribute<TXx, String> xxBz;
  public static volatile SingularAttribute<TXx, String> xxDm;
  public static volatile SingularAttribute<TXx, String> xxLx;
  public static volatile SingularAttribute<TXx, String> xxMc;
  public static volatile SingularAttribute<TXx, Integer> xxXh;
  public static volatile SingularAttribute<TXx, String> xxBy1;
  public static volatile SingularAttribute<TXx, String> xxBy2;
  public static volatile SingularAttribute<TXx, String> xxBy3;
  public static volatile SingularAttribute<TXx, Integer> xxBy4;
  public static volatile SingularAttribute<TXx, Integer> xxBy5;
  public static volatile SingularAttribute<TXx, Date> xxBy6;
  public static volatile SingularAttribute<TXx, Date> xxBy7;
  public static volatile SingularAttribute<TXx, Float> xxBy8;

}

 

六、配置Spring

在src下新建applicationContext.xml文件如下:

Xml代码

 

七、建立Junit测试单元

新建一个类:test.com.strong.StringOpenJPATest

Java代码
package test.com.strong;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class StringOpenJPATest {

  // 使用注解的方式注入,3.1以前版本使用JpaDaoSupport和JpaTemplate实现
  @PersistenceContext
  private EntityManager entityManager;

  @Test
  public void doTest() {
    System.out.println("=====Hello OpenJPA " + entityManager + "=======");
  }

}

这里和Spring3.1以前的版本有一些不同,具体内容请参见Spring3.1+ JpaDaoSupport被deprecated后的研究

 

执行测试获得结果如下:

Cpp代码
......
=====Hello OpenJPA Shared EntityManager proxy for target factory [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@6087e704]=======
.......

到这里,我们成功的运行起来Spring+OpenJPA,并获取了对应的EntityManager,下一步将在这个的基础之上其他的操作,因为我是按照最初始的步骤进行的,所以现在的配置文件正式运行可能定存在问题,下节将进行详细的介绍

 

 

http://simen-net.iteye.com/blog/1477748

------OpenJPA的增强器(Enhancer)能够在运行时对系统性能进行优化,并且提高惰性加载的灵活性,是OpenJPA与Hibernate最大不同之处。增强器能够自动为持久化的类添加一些代码,这些代码能够帮助二进制的类实现持久化类所必需的一些特性。OpenJPA的增强器可以通过两种方式对持久化类进行优化,一是编译时强化;二是使用Java 5 提供的新特性Instrumentation,在运行时创建代理来强化。

 

这个是OpenJPA的一大特点,很多人在刚开始接触的时候很容易因为这个出错,因为OpenJPA默认是开启了编译时强化,我最开始使用OpenJPA的时候就经历了下面的过程。

 

我们现在修改上次Test代码:

Java代码
  @Test
  public void doTest() {
    System.out.println("=====Hello OpenJPA " + entityManager + "=======");
    TXx txx = new TXx();
    txx.setXxMc("第一选项");
    entityManager.persist(txx);
  }

运行后报错如下:

Html代码
.............
<openjpa-2.1.1-r422266:1148538 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "
com.strong.module.txx.jpa.TXx".
.............

解决的方法有三种:

 

第一,在我之前的文章写过,就是使用Spring的Instrumentation(传送门Spring3(MVC)+OpenJPA2构建及发布 ),这个方法的缺点就是发布的时候在Tomcat的启动配置中也需要增加-javaagent:/simen/workspace/tomcat/lib/spring-agent.jar,且效率不高。下面列出我之前文章的内容给大家参考一下,不建议大家在实际中使用:

 

----当初为这个把我郁闷的,去 OpenJPA和Spring网站翻了半天才知道tomcat启动的时候要注册一个agent,名字叫spring-agent.jar,兴奋……翻遍 spring的包没找到这个东东  狂晕……,求教Google半天从一个犄角旮旯发现2.5这个包换名字,现在是org.springframework.instrument- 3.0.1.RELEASE-A.jar,找到2.5的spring-agent.jar才发现本来包里面的路径名就应该是instrument。把这个包改成spring-agent.jar(本身那个太长了),放到tomcat/lib目录里面,然后给tomcat加上启动参数  -javaagent:/simen/workspace/tomcat/lib/spring-agent.jar,在Eclipse里面是右键点这个项目,Debug as -> Debug Configrations....

 

第二,在persistence.xml中增加如下:

Xml代码

这个方法最简单,可惜不能发挥OpenJPA的最大效能,所以也不推荐

 

第三,终极解决方案(参考http://www.ibm.com/developerworks/cn/java/j-lo-openjpa2/ )对每个持久化类执行

Cpp代码
java org.apache.openjpa.enhance.PCEnhancer TXx.java

介个.......太麻烦了..............我还是不用了吧,不过等等,OpenJPA官方提供了几种解决方法,参见http://openjpa.apache.org/entity-enhancement.html ,如果使用的是Eclipse,那么还有无缝解决方案,参见http://openjpa.apache.org/enhancement-with-eclipse.html ,这里我使用的是Eclipse增加Ant编译的方法,过程如下(简单翻译官方文档,E文较差大家将就):

 

1、下载enhance.xml.tar.gz 解压到项目的根目录;新建openjpa_libs目录,下载与项目maven中openjpa版本相同openjpa-all 的jar包到这个目录(千万不要直接用openjpa-****.jar,必须是openjpa-all-*****.jar ),刷新项目保证能看增加的内容

 

2、右键项目,选择属性,进入Builders

 

3、在Main选项卡,新建一个Ant Builder,Buildfile的点“Browse Workspace”,选择上面的那个xml文件

 

Base Directory的点“Variables ”,选择build_project

 

最后填写Arguments的内容如图:

 

4、在Targets选项卡中为Manual Build 和 Auto Build点“Set Targets..”添加enhance


 

5、保存后控制台提示Ant Build的信息如下(不能显示的话刷新项目):

Cpp代码
Buildfile: /simen/ramwork/StrongOpenJPA/enhance.xml

openjpa.libs.check:

build.dir.check:

enhance:
        [echo] /simen/ramwork/StrongOpenJPA/target/classes:/simen/ramwork/StrongOpenJPA/openjpa_libs/openjpa-all-2.2.0.jar
    [openjpac] 299  StrongOpenJPAPU  INFO   [Worker-44] openjpa.Tool - Enhancer running on type "com.strong.module.txx.jpa.TXx".
BUILD SUCCESSFUL
Total time: 1 second

这里提示TXx类在编译的时候被增强,再次运行Test,运行通过

 

本节成功的把TXx增强了起来,如果大家觉得麻烦也可以直接枪毙了这个增强,或者在开发过程中不增强只是在发布的时候增强一下,恩这个主意不错!

可能大家会发现一个问题,刚才的Test执行了,但是数据库的内容没有变化,为什么?当然是事务的问题,这个问题下节我们继续。

 

本节资源:

OpenJPA官方提供的Eclipse增强xml:enhance.xml.tar.gz

本节的源码(内含openjpa-2.2.0.jar,上节源码在maven中没有MySQL的JDBC,本节已默认增加):StrongOpenJPA.tar.gz

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值