`
simen_net
  • 浏览: 300926 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

跟我学OpenJPA之四(与其他JPA实现的互换与对比---实践是检验真理的唯一标准)

 
阅读更多

 

感谢jinnianshilongnian和kjj的建议,我已经修改了文章的标题,以后会多多注意细节

 

上节,我们已经成功的把OpenJPA的实体对象增强,那么问题出现了。为什么我们要花费如此的代价,去修改实体类的字节码。这些修改能在实际的应用中体现出优化吗?在写这篇文章之前,我也没有针对这个做过完整的测试,实践是检验真理的唯一标准,那么让我们用实际行动来检验之。

 

本来想专门开一节讲解如何快速的将项目从OpenJPA转换到其他的JPA实现,但是由于确实太简单,单独一章介绍似乎有赚稿费的嫌疑(^_^) ,那么就在这里把项目转换到Hibernate和EclipseLink的JPA实现,同时也好与他们做个简单的性能比较。

 

================介绍完毕的分割线====================

 

在上节的测试中,我们发现entityManager.persist(entity)并没有把数据持久化保存到数据库,显然是因为没有启用事务的原因。在测试开始之前,我们先修改一下之前的代码。

 

1、建立DAO类

接口:StrongDAO.java

public abstract interface StrongDAO<E, PK extends Serializable> {

  /**
   * 执行SQL
   * 
   * @param strSQL
   * @return
   */
  public int executeSQL(final String strSQL);

  /**
   * 保存实体到数据库
   * 
   * @param entity
   */
  public void save(final E entity);
} 

实现:StrongDAOImpl.java

public abstract class StrongDAOImpl<E, PK extends Serializable> implements StrongDAO<E, PK> {

  @PersistenceContext
  private EntityManager entityManager;

  public EntityManager getEntityManager() {
    return this.entityManager;
  }

  public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
  }

  @Override
  public int executeSQL(String strSQL) {
    // TODO Auto-generated method stub
    return entityManager.createNativeQuery(strSQL).executeUpdate();
  }

  @Override
  public void save(E entity) {
    entityManager.persist(entity);
  }
}

 

2、为便于事务管理,建立Service类

接口:TXxService.java

@Transactional
public interface TXxService {

  /**
   * 单事务循环插入1000
   */
  public void doDanSHiWuXunHuan1000();

  /**
   * 单事务循环插入2000
   */
  public void doDanSHiWuXunHuan2000();

  /**
   * 单事务循环插入8000
   */
  public void doDanSHiWuXunHuan8000();

  /**
   * 单事务循环插入20000
   */
  public void doDanSHiWuXunHuan20000();

  /**
   * 使用事务添加单条记录
   */
  public void doShiWuTianJia(TXx txx);

  /**
   * 直接执行SQL清空记录
   */
  public void doQingKong();
}

实现:TXxServiceImpl.java

@Service
public class TXxServiceImpl implements TXxService {

  @Autowired
  public TXxDAO txxDAO;

  private void doDanSHiWuXunHuan(int intCiShu) {
    for (int i = 0; i < intCiShu; i++) {
      TXx txx = new TXx();
      txx.setXxMc("第一选项" + i);
      txxDAO.save(txx);
    }
  }

  @Override
  public void doDanSHiWuXunHuan1000() {
    doDanSHiWuXunHuan(1000);
  }

  @Override
  public void doDanSHiWuXunHuan2000() {
    doDanSHiWuXunHuan(2000);
  }

  @Override
  public void doDanSHiWuXunHuan8000() {
    doDanSHiWuXunHuan(8000);
  }

  @Override
  public void doDanSHiWuXunHuan20000() {
    doDanSHiWuXunHuan(20000);
  }

  @Override
  public void doShiWuTianJia(TXx txx) {
    txxDAO.save(txx);
  }

  @Override
  public void doQingKong() {
    System.out.println(txxDAO.executeSQL("delete from t_xx where xx_id > 22"));
  }
}

 

4、修改pom.xml,导入Hibernate的JPA实现包和EclipseLink的包,增加如下:

    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.3.2</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>4.1.0.Final</version>
    </dependency>

 

5、修改persistence.xml便于随时转换为其他的JPA实现

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="StrongOpenJPAPU" transaction-type="RESOURCE_LOCAL">
    <!-- 使用OpenJPA -->
    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
    <!-- 使用Hibernate-JPA 
    <provider>org.hibernate.ejb.HibernatePersistence</provider>-->
    <!-- 使用EclipseLink
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> -->
    <class>com.strong.module.txx.jpa.TXx</class>
    <properties>
      <!-- JPA标准配置 使用OpenJPA和EclipseLink时使用 -->
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/strongjpa" />
      <property name="javax.persistence.jdbc.user" value="root" />
      <property name="javax.persistence.jdbc.password" value="root" />
      
      <!-- OpenJPA不增强 -->
      <property name="openjpa.ClassLoadEnhancement" value="false" />
      <property name="openjpa.DynamicEnhancementAgent" value="false" />
      <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
      
      <!-- Hibernate配置  使用Hibernate的JPA实现时使用
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
      <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/strongjpa" />
      <property name="hibernate.connection.username" value="root" />
      <property name="hibernate.connection.password" value="root" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />-->

    </properties>
  </persistence-unit>
</persistence>

两点需要注意:

1、由于Hibernate的顽固,不兼容标准的javax.persistence.jdbc.driver等参数,所以这里只能使用Hibernate自己的配置参数。

2、从增强OpenJPA转换到非增强OpenJPA的时候,首先要把上节中增加的Ant Builder禁用,然后要修改一次TXx类,以便Eclipse重新编译他,否则运行的时候使用的依然是增强过的实体对象。

3、EclipseLink运行的时候,必须给VM增加参数:-javaagent:****/spring-instrument-****.jar,否则会报错。使用的方法请参见上节中的介绍或参见Spring3(MVC)+OpenJPA2构建及发布

 

通过以上修改,大家很容易就发现:有了JPA的接口,我们可以非常方便地转换其他的实现,在Spring3.1之前,仍然使用回调的方式实现DAO,这样还会与JPA的具体实现有部分耦合,Spring3.1之后的注入方式彻底实现了解耦合。所以这里强烈大家升级到3.1以上并修改之前的耦合部分。

 

6、修改测试单元

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

  @Autowired
  public TXxService txxService;

  private void doDuoShiWuXunHuan(int intCiShu) {
    for (int i = 0; i < intCiShu; i++) {
      TXx txx = new TXx();
      txx.setXxMc("第一选项" + i);
      txxService.doShiWuTianJia(txx);
    }
  }

  @Test
  public void doCeShiDuoShiWuXunHuan100() {
    doDuoShiWuXunHuan(100);
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDuoShiWuXunHuan200() {
    doDuoShiWuXunHuan(200);
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDuoShiWuXunHuan800() {
    doDuoShiWuXunHuan(800);
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDuoShiWuXunHuan2000() {
    doDuoShiWuXunHuan(2000);
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDanSHiWuXunHuan1000() {
    txxService.doDanSHiWuXunHuan1000();
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDanSHiWuXunHuan2000() {
    txxService.doDanSHiWuXunHuan2000();
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDanSHiWuXunHuan8000() {
    txxService.doDanSHiWuXunHuan8000();
    txxService.doQingKong();
  }

  @Test
  public void doCeShiDanSHiWuXunHuan20000() {
    txxService.doDanSHiWuXunHuan20000();
    txxService.doQingKong();
  }
}

测试顺序是先执行循环多次事务,每次事务插入一条记录(数量分别为100,200,800,2000);然后执行一次事务插入多条记录(数量分别为1000,2000,8000,20000),下面是测试的对比图

 



 

结论:

      分析结果我们发现,OpenJPA使用增强后的实体对象相较未增强时有明显性能提升,对比其他的JPA实现,OpenJPA的性能也没有太大的差别,尤其是在单事务多操作时其性能相较其他两种也有一定的优势。奇怪的时OpenJPA在连续执行多个简单事务时性能明显滞后。

      OpenJPA的官方文档中说实体对象增强后在“延迟加载”、“脏检查”等方面性能有一定的优化,由于时间和精力有限这里就不对这两项进行测试,把这个任务留给大家吧^_^

 

 

      最后,希望通过本节能让大家接受JPA,认可OpenJPA。从之前三篇文章的情况来看,感兴趣的朋友还是不多。顺便介绍一个OpenJPA入门和学习非常好课程:使用 Apache OpenJPA 开发 EJB 3.0 应用系列 有兴趣的朋友请传送过去学习。

      之前有人问我为什么不写写OpenJPA的基础概念和研究,其实主要是对比这个系列我觉得我的能力和协作的水平确实有限,并且也没有必要重复他人的工作。

 

本节资源:

本节的源码:StrongOpenJPA.tar.gz

Ant Builder需要的openjpa-all的jar包:openjpa_libs.tar.gz

 

  • 大小: 34.9 KB
  • 大小: 35.7 KB
分享到:
评论
1 楼 zn.share 2012-07-12  
实事求是的情深很好

相关推荐

    openjpa-manual

    JPA Overview and OpenJPA Reference Guide

    apache-openjpa-2.2.1-source

    OpenJPA 是 Apache 组织提供的开源项目,它实现了 EJB 3.0 中的 JPA 标准,为开发者提供功能强大...OpenJPA 可以作为独立的持久层框架发挥作用,也可以轻松的与其它 Java EE 应用框架或者符合 EJB 3.0 标准的容器集成。

    OpenJPA 2.2.1 API (CHM格式)

    OpenJPA 可以作为独立的持久层框架发挥作用,也可以轻松的与其它 Java EE 应用框架或者符合 EJB 3.0 标准的容器集成。  除了对 JPA 标准的支持之外,OpenJPA 还提供了非常多的特性和工具支持让企业应用开发变得更加...

    Apache OpenJPA 2.1 User's Guide

    OpenJPA is Apache's implementation of Sun's Java Persistence 2.0 API (JSR-317 JPA 2.0) specification for the transparent persistence of Java objects. This document provides an overview of the JPA ...

    openJPA官方手册

    openJPA官方手册,openJPA官方手册openJPA官方手册

    openjpa范例及实例工程

    默认情况下,当应用程序第一次获取实体标识时,OpenJPA 框架从数据库中一次性获取 50 个连续的实体标识缓存起来,当下一次应用程序需要获取实体标识时,OpenJPA 将首先检测缓存中是否存在实体标识,如果存在,Open...

    jsf、openJpa学习

    jsf 入门知识 ,jsf标签,jsf与openJpa整合,jsf与Spring整合

    apache-openjpa-3.1.0-binary.zip

    JPA规范要求对实体对象进行某种类型的监视,但是该规范并未定义如何实现此监视。一些JPA提供程序动态生成在用户的Entity对象前面的新子类或代理对象,而其他JPA提供程序使用字节码编织技术来增强实际的Entity类对象...

    openjpa-1.1.0.jar

    apache的jpa,版本是1.1.0的,apache主页上能找的到

    OpenJPA API 文档 chm格式

    OpenJPA API 文档 chm格式

    Open JPA2 employee 简单例子

    Open JPA2 employee 简单例子

    Openjpa手册

    OpenJPA OpenJPA 是 Apache 组织提供的开源项目,它实现了 EJB 3.0 中的 JPA 标准,为开发者提供功能强大、使用简单的持久化数据管理框架。

    openjpa实体标识的生成策略

    OpenJPA 是 Apache 组织提供的 JPA 标准实现。本文是 使用 Apache OpenJPA 开发 EJB 3.0 应用系列 的第五部分,介绍在 OpenJPA 中如何自动生成实体的唯一标识,包括使用容器自动生成实体标识,借助于数据库的自动...

    openjpa 写的一个例子

    自己用openjpa些的一个基于web 的例子

    Spring中使用OpenJPA

    Spring中使用OpenJPA源代码 博文链接:https://lxy19791111.iteye.com/blog/184997

    apache-openjpa-2.2.1-binary

    apache-openjpa-2.2.1-binary

    Spring和openJPA集成

    NULL 博文链接:https://laoli5290.iteye.com/blog/2088341

    openjpa:Apache OpenJPA

    Apache OpenJPA是Java Persistence API规范的实现。 执照 此存储库的内容已根据Apache License 2.0 许可 更多信息 可以在openjpa-project子目录中找到以下文件: openjpa-project / BUILDING.txt openjpa-project...

    JPA教程,包括TOPLink JPA,Hibernate JPA,Open Jpa,jpa批注

    包括TOPLink JPA,Hibernate JPA,Open Jpa,jpa批注

    apache-openjpa-2.2.0-source.zip

    apache-openjpa-2.2.0-source.zip

Global site tag (gtag.js) - Google Analytics