精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-08
最后修改:2012-04-09
接上节:跟我学OpenJPA之三(Entity实体对象增强--更快、更高、更强)
感谢jinnianshilongnian和kjj的建议,我已经修改了文章的标题,以后会多多注意细节
上节,我们已经成功的把OpenJPA的实体对象增强,那么问题出现了。为什么我们要花费如此的代价,去修改实体类的字节码。这些修改能在实际的应用中体现出优化吗?在写这篇文章之前,我也没有针对这个做过完整的测试,实践是检验真理的唯一标准,那么让我们用实际行动来检验之。
本来想专门开一节讲解如何快速的将项目从OpenJPA转换到其他的JPA实现,但是由于确实太简单,单独一章介绍似乎有赚稿费的嫌疑(^_^) ,那么就在这里把项目转换到Hibernate和EclipseLink的JPA实现,同时也好与他们做个简单的性能比较。
================介绍完毕的分割线====================
在上节的测试中,我们发现entityManager.persist(entity)并没有把数据持久化保存到数据库,显然是因为没有启用事务的原因。在测试开始之前,我们先修改一下之前的代码。
1、建立泛型的DAO类,其他各实体对象的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、实体对象的DAO,有了泛型的DAO,那么实体就简单多了 接口:TXxDAO.java package com.strong.module.txx.jpa; import com.strong.dao.StrongDAO; /** * TXxDAO * * @author Simen 自动生成时间: 2011-10-02 08:31:29 */ public interface TXxDAO extends StrongDAO<TXx, Integer> { }
实现:TXxDAOImpl.java package com.strong.module.txx.jpa; import org.springframework.stereotype.Repository; import com.strong.dao.StrongDAOImpl; /** * TXxDAO * * @author Simen 自动生成时间: 2011-10-02 08:31:29 */ @Repository public class TXxDAOImpl extends StrongDAOImpl<TXx, Integer> implements TXxDAO { }
3、为便于事务管理,建立Service类,再接口上注解@Transactional,这样所有的方法都开启了事务,对于只读的方法单独注解为如下,当然也可以单独给所有的方法注册事务。 @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
接口: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在连续执行多个简单事务时性能明显滞后。 由于全部采用默认配置,不同实现的默认参数并不尽相同,部分性能的差距完全可以采用不同的优化来弥补,但是至少通过测试我们可以肯定JPA的各类实现性能基本相近,并且可以完全平滑地互相转移。 另:OpenJPA的官方文档中说实体对象增强后在“延迟加载”、“脏检查”等方面性能有一定的优化,由于时间和精力有限这里就不对这两项进行测试,把这个任务留给大家吧^_^
最后,希望通过本节能让大家接受JPA,认可OpenJPA。从之前三篇文章的情况来看,感兴趣的朋友还是不多。顺便介绍一个OpenJPA入门和学习非常好课程:使用 Apache OpenJPA 开发 EJB 3.0 应用系列 有兴趣的朋友请传送过去学习。 之前有人问我为什么不写写OpenJPA的基础概念和研究,其实主要是对比这个系列我觉得我的能力和写作的水平确实有限,并且也没有必要重复他人的工作。
本节资源: 本节的源码:StrongOpenJPA.tar.gz Ant Builder需要的openjpa-all的jar包:openjpa_libs.tar.gz
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-04-09
兄弟你写的好快啊,我现在的springMVC好多天都磨不出一节 哈哈哈
|
|
返回顶楼 | |
发表时间:2012-04-10
jinnianshilongnian 写道 兄弟你写的好快啊,我现在的springMVC好多天都磨不出一节 哈哈哈
简单的一些过程而已,没有复杂理论,好写很多 |
|
返回顶楼 | |
发表时间:2012-04-10
简洁明了
抽时间得细琢磨琢磨 |
|
返回顶楼 | |
发表时间:2012-04-10
似乎看不到 openJPA 有什么特别的优势啊。有什么使用 openJPA 的特别的理由吗?
|
|
返回顶楼 | |
发表时间:2012-04-10
测试过OpenJPA与Hibernate二者之间的性能问题吗
|
|
返回顶楼 | |
发表时间:2012-04-10
lqixv 写道 似乎看不到 openJPA 有什么特别的优势啊。有什么使用 openJPA 的特别的理由吗?
持久化实现现在基本都不存在太大的差异 之所以选择OpenJPA 首先,JPA的标准实现,相比Hiberntae自己的标准开放很多; 其次,Apache的东西,从开源和今后的授权来看Apache的东西比较值得信任 最后,社区活跃程度和升级发布速度都还不错 |
|
返回顶楼 | |
发表时间:2012-04-10
maoweiwer 写道 测试过OpenJPA与Hibernate二者之间的性能问题吗
如果硬要直接和Hibernate比较可比性不高,由于Hibernate的JPA实现就是基于基础的Hibernate Core,所以和这个进行比较更能说明问题。 |
|
返回顶楼 | |
发表时间:2012-04-10
OpenJPA的实现相对于JPA规范更灵活,有些JPA不支持的,OpenJPA反而支持
|
|
返回顶楼 | |
发表时间:2012-04-10
扩展JPA的支持这个是必然的,不然大家都长一个面孔还有什么意义
|
|
返回顶楼 | |