我喜欢集成测试,这是检查Hibernate生成哪些幕后花絮SQL查询的好方法。 但是集成测试需要运行的数据库服务器,这是您必须要做的第一选择。

1.使用类似生产的本地数据库服务器进行集成测试

对于生产环境,我始终喜欢使用增量DDL脚本,因为我始终可以知道在给定服务器上部署了哪个版本,以及哪些是需要部署的较新脚本。 我一直依靠Flyway来为我管理模式更新,对此我非常满意。

在集成测试量很小的小型项目中,您也可以使用类似于生产的本地数据库服务器进行测试。 这是最安全的选择,因为它可以确保您在生产设置非常相似的环境中进行测试。

主要缺点是测试速度。 使用外部数据库意味着额外的时序成本,这很容易在大型项目中失控。 毕竟,谁喜欢每天运行60分钟的测试程序?

2.内存数据库集成测试

我选择使用内存数据库进行集成测试的原因是为了加快测试的运行时间。 这是一个影响测试运行时间的方面,还有许多其他方面可能会影响您,例如销毁和重新创建包含大量Bean依赖项的Spring应用程序上下文。

您可以选择许多内存数据库: HSQLDB , H2 , Apache Derby ,仅举几例。

我一直在使用两种内存中架构生成策略,它们都有优点和缺点,下面将对它们进行解释。

2.1利用hibernate.hbm2ddl.auto =” update”

Hibernate在配置它时非常灵活。 幸运的是,我们可以使用“ hibernate.hbm2ddl.auto” SessionFactory属性来自定义DDL生成。

部署架构的最简单方法是使用“更新”选项。 这对于测试目的很有用。 在生产环境中我不会依赖它,对于增量环境而言,增量DDL脚本是一种更好的方法。

因此,选择“更新”选项是Integration Testing架构管理的一种选择。

这就是我在Hibernate Facts代码示例中使用它的方式。

让我们从JPA配置开始,您可以在META-INF / persistence.xml文件中找到:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd"><persistence-unit name="testPersistenceUnit" transaction-type="JTA"><provider>org.hibernate.ejb.HibernatePersistence</provider><exclude-unlisted-classes>false</exclude-unlisted-classes><properties><property name="hibernate.archive.autodetection"value="class, hbm"/><property name="hibernate.transaction.jta.platform"value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform" /><property name="hibernate.dialect"value="org.hibernate.dialect.HSQLDialect"/><em><property name="hibernate.hbm2ddl.auto"value="update"/></em><property name="hibernate.show_sql"value="true"/></properties></persistence-unit>
</persistence>

并且dataSource配置如下所示:

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"><constructor-arg><bean class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"destroy-method="close"><property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/><property name="uniqueName" value="testDataSource"/><property name="minPoolSize" value="0"/><property name="maxPoolSize" value="5"/><property name="allowLocalTransactions" value="true" /><property name="driverProperties"><props><prop key="user">${jdbc.username}</prop><prop key="password">${jdbc.password}</prop><prop key="url">${jdbc.url}</prop><prop key="driverClassName">${jdbc.driverClassName}</prop></props></property></bean></constructor-arg></bean>

我认为Bitronix是我使用过的最可靠的工具之一。 在开发JEE应用程序时,我利用了使用中的Application Server提供的Transaction Manager。 对于基于Spring的项目,我必须雇用独立的事务管理器,在评估JOTM,Atomikos和Bitronix之后,我选择了Bitronix。 那是5年前,自从我部署并使用了几个应用程序以来。

即使应用程序当前仅使用一个数据源,我还是更喜欢使用XA Transactions。 我不必担心使用JTA会明显降低性能,因为当当前事务仅使用一个登记的数据源时,Bitronix使用1PC(单阶段提交) 。 由于最后一次资源提交的优化,它还可以添加多达一个非XA数据源。

使用JTA时,建议不要混合使用XA和本地事务,因为并非所有XA数据源都允许在本地事务中进行操作,因此我倾向于尽可能避免这种情况。

不幸的是,就像这种DDL生成方法一样简单,它有一个我不太喜欢的缺陷。 我不能禁用“ allowLocalTransactions”设置,因为Hibernate会创建DDL脚本并在XA事务之外对其进行更新。

另一个缺点是,您几乎无法控制Hibernate代表您部署的DDL脚本,并且在这种特定情况下,我不希望牺牲灵活性而不是方便性。

如果您不使用JTA并且不需要灵活决定将在当前数据库服务器上部署什么DDL模式,那么hibernate.hbm2ddl.auto =” update”可能是您的正确选择。

2.2灵活的架构部署

此方法包括两个步骤。 前者将使Hibernate生成DDL脚本,而后者将以自定义方式部署它们。

要生成DDL脚本,我必须使用以下Ant任务(即使正在通过Maven运行),这是因为在编写本文时,我没有可以使用的Hibernate 4 Maven插件:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><executions><execution><id>generate-test-sql-scripts</id><phase>generate-test-resources</phase><goals><goal>run</goal></goals><configuration><tasks><property name="maven_test_classpath" refid="maven.test.classpath"/><path id="hibernate_tools_path"><pathelement path="${maven_test_classpath}"/></path><property name="hibernate_tools_classpath" refid="hibernate_tools_path"/><taskdef name="hibernatetool"classname="org.hibernate.tool.ant.HibernateToolTask"/><mkdir dir="${project.build.directory}/test-classes/hsqldb"/><hibernatetool destdir="${project.build.directory}/test-classes/hsqldb"><classpath refid="hibernate_tools_path"/><jpaconfiguration persistenceunit="testPersistenceUnit"propertyfile="src/test/resources/META-INF/spring/jdbc.properties"/><hbm2ddl drop="false" create="true" export="false"outputfilename="create_db.sql"delimiter=";" format="true"/><hbm2ddl drop="true" create="false" export="false"outputfilename="drop_db.sql"delimiter=";" format="true"/></hibernatetool></tasks></configuration></execution></executions>...
</plugin>

有了“创建”和“删除” DDl脚本后,我们现在必须在Spring上下文启动时部署它们,这是使用以下定制Utility类完成的:

public class DatabaseScriptLifecycleHandler implements InitializingBean, DisposableBean {private final Resource[] initScripts;private final Resource[] destroyScripts;private JdbcTemplate jdbcTemplate;@Autowiredprivate TransactionTemplate transactionTemplate;private String sqlScriptEncoding = "UTF-8";private String commentPrefix = "--";private boolean continueOnError;private boolean ignoreFailedDrops;public DatabaseScriptLifecycleHandler(DataSource dataSource,Resource[] initScripts,Resource[] destroyScripts) {this.jdbcTemplate = new JdbcTemplate(dataSource);this.initScripts = initScripts;this.destroyScripts = destroyScripts;}public void afterPropertiesSet() throws Exception {initDatabase();}public void destroy() throws Exception {destroyDatabase();}public void initDatabase() {final ResourceDatabasePopulator resourceDatabasePopulator = createResourceDatabasePopulator();transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {jdbcTemplate.execute(new ConnectionCallback<Void>() {@Overridepublic Void doInConnection(Connection con) throws SQLException, DataAccessException {resourceDatabasePopulator.setScripts(getInitScripts());resourceDatabasePopulator.populate(con);return null;}});return null;}});}public void destroyDatabase() {final ResourceDatabasePopulator resourceDatabasePopulator = createResourceDatabasePopulator();transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {jdbcTemplate.execute(new ConnectionCallback<Void>() {@Overridepublic Void doInConnection(Connection con) throws SQLException, DataAccessException {resourceDatabasePopulator.setScripts(getDestroyScripts());resourceDatabasePopulator.populate(con);return null;}});return null;}});}protected ResourceDatabasePopulator createResourceDatabasePopulator() {ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();resourceDatabasePopulator.setCommentPrefix(getCommentPrefix());resourceDatabasePopulator.setContinueOnError(isContinueOnError());resourceDatabasePopulator.setIgnoreFailedDrops(isIgnoreFailedDrops());resourceDatabasePopulator.setSqlScriptEncoding(getSqlScriptEncoding());return resourceDatabasePopulator;}
}

配置为:

<bean id="databaseScriptLifecycleHandler" class="vladmihalcea.util.DatabaseScriptLifecycleHandler"depends-on="transactionManager"><constructor-arg name="dataSource" ref="dataSource"/><constructor-arg name="initScripts"><array><bean class="org.springframework.core.io.ClassPathResource"><constructor-arg value="hsqldb/create_db.sql"/></bean></array></constructor-arg><constructor-arg name="destroyScripts"><array><bean class="org.springframework.core.io.ClassPathResource"><constructor-arg value="hsqldb/drop_db.sql"/></bean></array></constructor-arg>
</bean>

这次我们可以摆脱任何本地交易,因此可以安全地设置:

<property name="allowLocalTransactions" value="false" />
  • 代码可在GitHub上获得 。
参考: Hibernate Fact:来自我们的JCG合作伙伴 Vlad Mihalcea的集成测试策略 ,位于Vlad Mihalcea的Blog博客上。

翻译自: https://www.javacodegeeks.com/2013/12/hibernate-facts-integration-testing-strategies.html

Hibernate事实:集成测试策略相关推荐

  1. 休眠事实:集成测试策略

    我喜欢集成测试,这是检查Hibernate生成哪些幕后花絮的SQL查询的好方法. 但是集成测试需要运行的数据库服务器,这是您必须要做的第一选择. 1.使用类似生产的本地数据库服务器进行集成测试 对于生 ...

  2. Spring+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务

    一.概念 分布式事务 分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.简言之,同时操作多个数据库保持事务的统一,达到跨库事务的效果. JT ...

  3. Spring MVC Hibernate MySQL集成CRUD示例教程

    Spring MVC Hibernate MySQL集成CRUD示例教程 我们在上一篇教程中学习了如何集成Spring和Hibernate.今天,我们将继续前进,并将Spring MVC和Hibern ...

  4. mvc crud_Spring MVC Hibernate MySQL集成CRUD示例教程

    mvc crud We learned how to integrate Spring and Hibernate in our last tutorial. Today we will move f ...

  5. 软考考点之集成测试策略

    把自己总结的这些错题和考点,好好的看一遍,那么考试就很简单了,一定会过的,不要像扒子一样,随扒随露.      ---11.2于济南 如2016年上半年 第34题:下图(a)所示为一个模块层次结构的例 ...

  6. spring和hibernate的集成

    集成关系图: 项目目录树: User.java package com.donghai.bean;public class User {private String id;private String ...

  7. jsf集成spring_JSF 2,PrimeFaces 3,Spring 3和Hibernate 4集成项目

    jsf集成spring 本文展示了如何集成JSF2,PrimeFaces3,Spring3和Hibernate4技术. 它为Java开发人员提供了一个通用的项目模板. 另外,如果Spring不用于业务 ...

  8. JSF 2,PrimeFaces 3,Spring 3和Hibernate 4集成项目

    本文展示了如何集成JSF2,PrimeFaces3,Spring3和Hibernate4技术. 它为Java开发人员提供了一个通用的项目模板. 另外,如果Spring不用于业务和数据访问层,则可以提供 ...

  9. Hibernate缓存集成IMDG

    1 第三方缓存插件 除了Ehcache这种轻量级的缓存方案外,几乎所有IMDG产品都提供了对Hibernate二级缓存的直接支持,常用的有: Ø  Hazelcast Ø  GridGain Ø  J ...

最新文章

  1. JavaScript封装一个注册函数解决兼容问题
  2. 收藏|最优论文+代码查找神器,覆盖AI全领域(966个ML任务、8500+论文)
  3. python开源报表系统_流程设计器、表单设计器和简单报表管理开源OA系统smart-web...
  4. python为什么这么火 知乎-没想到吧!Google 排名第一的编程语言,为什么会这么火?...
  5. java语言for模板_java版的模板语言
  6. 跟优秀的人一起进步:四月组队学习
  7. Cheatsheet: 2013 09.10 ~ 09.21
  8. 柔性体没有应变_柔性应变和压力传感器
  9. CompletableFuture详解~创建实例
  10. Android 系统(170)----收到短信,FM外放自动切回耳机
  11. 李炎恢的课程中心(JQUERY视频)
  12. 现代通信原理3.3:两个重要的信号处理模块-乘法器与滤波器
  13. php留言板入门教程,一个php留言板实例
  14. pythonmapdel_地质男转行学遥感Python——遥感数据裁剪的具体实现
  15. acer软件保护卡怎么解除_Acer和Founder软件保护卡驱动卸载方法
  16. CFA 2020 notes的PDF版本,热乎乎的百度网盘分享
  17. Starting Programe
  18. 盲盒识别装置-2022TI杯10月联赛D题
  19. 教你如何简单快速有效的添加微信好友
  20. 事务的四大属性ACID即事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability.。...

热门文章

  1. Java中的List你真的会用吗
  2. 零配置 之 Spring 概述
  3. 关联分析:FP-Growth算法
  4. 《四世同堂》金句摘抄(十八)
  5. com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML
  6. 当当网头部和尾部——CSS源码
  7. 创建对象并且使用对象的属性和方法
  8. 用startSmoothScroll实现RecyclerView滚动到指定位置并置顶,含有动画。
  9. c语言模拟题答案及解析,全国计算机等考二级C语言模拟试题,答案及解析一
  10. ffmpeg中文开发手册_快速调用复杂命令,支持中文注释,命令行备忘工具navi两天就火了...