加速Hibernate初始化

时间:2014-09-22 18:56:16

标签: java hibernate jpa tdd embedded-database

我正在使用在JBoss 7上运行的Java EE应用程序。为了进行TDD,我正在设置使用Arquillian和嵌入式Weld以及H2嵌入式数据库的嵌入式测试。

这很好用,但是Hibernate的初始启动需要相当长的时间(5-10秒),而我还没有包含所有JPA实体。我试图使用持久化的Oracle DB来避免创建表,但它并没有太大的区别。

主要问题似乎是Hibernate遍历所有实体并验证并准备所有CRUD方法,命名查询等等。

有没有办法告诉Hibernate在需要时(或根本不是)懒洋洋地做这件事?大多数情况下,测试用例中只会包含一部分实体和查询,因此我很乐意在执行时将执行时间换成启动时间。

有什么想法吗?

我知道我可以使用实体的一个子集,但有时候很困难,因为它们通常与测试环境中不需要的其他实体有关系。或者是否有一种简单的方法可以“停用”这种关系以生成数据库的子集?

澄清

它接近它并不清楚我的问题是什么,所以我会试着澄清一下:

  • 我已经使用Arquillian(嵌入式Weld)建立了一个测试环境,该环境设置了一个嵌入式数据库(H2)来进行支持JPA的测试
  • 我想使用这种方法进行测试驱动开发(TDD),这意味着我将在我的本地开发机器上拥有以下工作流程:
    1. 创建测试用例
    2. 运行测试用例
    3. 如果测试用例失败,请执行必要的更改并返回2.
  • 通常情况下,在完成一项功能之前,我会先执行第2步和第3步,这意味着我将经常从我的IDE运行一次测试,该测试必须使用Arquillian,Weld,嵌入式数据库和整个测试JVM进行设置。无论如何只运行一次测试。

这个场景非常多。现在我注意到运行那个单一的测试需要大约10秒,这不是世界末日,而是需要很长时间才能完成TDD。当我进一步调查时,我注意到大部分时间都是由Hibernate设置其内部结构(它不是Weld,Arquillian,Schema创建或其他什么,但Hibernate准备提供EntityManager)。

所以我的问题是:有没有办法加快hibernate的初始化,所以我可以将这10秒减少到1-2秒?我不在乎它是否是一种黑客攻击(比如在多个手动测试运行期间保持测试JVM的hibernate活动或者停用一些Hibernate的验证或优化)。我唯一的问题是单次测试的启动时间。连续测试运行良好且快速,因此我没有完全回归测试或在构建服务器上进行测试的问题。

希望这让我的情况更加清晰......

1 个答案:

答案 0 :(得分:0)

我猜,您使用的是junit库?

数据库模式创建通常不是最耗时的操作(尽管它取决于实体的数量) 就个人而言,如果我是你,我将使用TestNG运行所有JUnit测试(是的,TestNG可以开箱即用地运行所有JUnit测试)并且会查看<your-module>/test-output/index.html(特别是其Chronological view部分和Times)。然后你会知道什么操作是最耗时的。有了这些信息,你可以走得更远。

此外,还有一些建议:

  1. 使用远程(或托管)容器的Arquillian测试通常更快,因为您只启动服务器一次。
  2. H2嵌入式数据库确实不是一个糟糕的选择。通常,您不必放弃它(通常,因为有时您的应用程序可能会使用H2中不存在的某些目标数据库功能。)
  3. 只有Arquillian Suite Extension允许您只部署一次并在测试类中重复使用它。在许多测试的情况下,此扩展可以显着加快测试执行速度。
  4. 您可以在任何容器外测试您的实体(所谓的standalone JPA transaction-type="RESOURCE_LOCAL")。这是最快的方法,但仅适用于测试实体注释,关系,查询等。

  5. 修改

    有很多方法可以更好地完成任务 只有几点:

    1. 您不必每次都重新创建数据库。即使是嵌入式数据库(H2,HSQLDB,Derby)也只有server mode,其持续时间比JVM长。
    2. 如果hibernate初始化困扰你,那么在所有测试中做一次(我的意思是在单元测试之间保持EntityManagerFactory)。
    3. 如果您想避免创建数据库,只需在服务器模式下使用H2并将hibernate设置为不进行任何更改(<property name="hibernate.hbm2ddl.auto" value="none" />
    4. 祝你好运