简体   繁体   中英

Speed Up Hibernate Initialization

I'm having a Java EE application that runs on JBoss 7. In order to do TDD, I'm setting up embedded tests that use Arquillian with embedded Weld and a H2 embedded database.

This works fine, but the initial startup of Hibernate takes a considerable amount of time (5-10 seconds) and I haven't included all JPA entities yet. I have tried to use a persisted Oracle DB instead to avoid table creation, but it doesn't make much of a difference.

The main problem seems to be that Hibernate goes through all the entities and validates and prepares all the CRUD methods, named queries and so on.

Is there any way to tell Hibernate to do this lazily when needed (or not at all)? Most of the time, there will only be a subset of entities and queries involved in a test case, so I'd happily trade in execution time for start-up time while implementing.

Any ideas?

I know I could just use a subset of the entities, but it's sometimes difficult as they often have relations to other entities not needed in a test context. Or is there an easy way to 'deactivate' such relations to generate subsets of the database?

Clarification

It seams like it's not clear what my problem is, so I'll try to clarify:

  • I have set up a testing environment with Arquillian (embedded Weld) that sets up an embedded database (H2) to do JPA enabled testing
  • I would like to use this approach to do Test Driven Development (TDD), which means I will have the following workflow on my local developing machine:
    1. Create test case
    2. Run test case
    3. If test case fails, implement necessary changes and go back to 2.
  • Normally, one will perform steps 2 and 3 a couple of times before finishing a feature which means that I will often run a single test from my IDE that has to set up the entire testing JVM with Arquillian, Weld, embedded DB and whatever to run just A SINGLE TEST.

So much for the scenario. Now I've noticed that running that single test takes around 10 seconds, which is not the end of the world, but rather long to do TDD. And when I further investigated, I've noticed that most of this time goes to Hibernate setting up its internal structures (it's not Weld, Arquillian, Schema creation or whatever, but Hibernate getting ready to provide an EntityManager).

So my question is: Is there a way to speed up hibernate initialization so I can drop these 10 seconds to maybe 1-2 seconds? I wouldn't care if it's sort of a hack (like keeping the testing JVM with hibernate alive during multiple manual test runs or deactivating some validations or optimizations of Hibernate). My only issue is the start up time for a single test. Consecutive tests run fine and fast, so I don't have a problem with full regression testing or with testing on my build server.

Hope that makes my case a bit clearer...

Let me guess, you are using junit library?

Database schema creation usually isn't the most time-consuming operation (although it depends on amount of entities).

Personally, if I were you, I would run all your JUnit tests with TestNG (yes, TestNG can run all JUnit tests out of the box) and would take a look at <your-module>/test-output/index.html (particularly its sections Chronological view and Times ). Then you would know what operations are the most time-consuming. And with such information, you can go further.

Furthermore, a couple of items of advice:

  1. Arquillian tests with a remote (or managed) containers are usually faster, because you start server only once.
  2. H2 embedded database isn't a bad choice, really. Typically you don't have to abandon it (typically, because sometimes your application may use some of the target database features, that are not present in the H2).
  3. There is Arquillian Suite Extension that lets you do deployment only once and reuse it across the test classes. In case of many tests, this extension can speed up tests execution significantly.
  4. You can test your entities outside any container (so called standalone JPA with transaction-type="RESOURCE_LOCAL" ). It is the fastest way, but suits well only for testing entities annotations, relations, queries and so on.

Edit

There is number of ways to do your task much better. Just a couple of points:

  1. You don't have to re-create database every time. Even embedded databases (H2, HSQLDB, Derby) have server mode in which they last longer than JVM.
  2. If Hibernate initialization bothers you, then do it once across the all tests (I mean keeping EntityManagerFactory between unit tests).
  3. If you want to avoid a database creation, just use H2 in server mode and set hibernate to not do any changes ( <property name="hibernate.hbm2ddl.auto" value="none" /> )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM