In-Memory Java DB 15.0.1.1 - Perfect For JPA-Unit testing
To install Java DB 10.5.1.1 you only have to download a ZIP file, extract it and put two JARs into your classpath. It comes with one major, killer feature - in-memory capability. I used Java DB for test purposes in embedded mode already. The database creates a folder in your local file system, what takes time and requires you to do some plumbing. This mode, however, is perfect if you needed a pre-populate database for your tests. You just had to copy the folder with an existing database into your test-project before your launch the tests and delete it afterwards.
With a in-memory connection: jdbc:derby:memory:sampledb;create=true you can create your database dynamically - and you don't even have to drop the tables afterwards.
To test it, I just adjusted the CRUD-Service configuration and measured the performance again. I didn't have to change anything in the unit-test:
public class CrudServiceBeanTest {
private EntityManager em;
private EntityTransaction et;
private CrudServiceBean crudServiceBean;
@Before
public void setUp() throws Exception {
this.em = Persistence.createEntityManagerFactory("test").createEntityManager();
this.et = this.em.getTransaction();
this.crudServiceBean = new CrudServiceBean();
this.crudServiceBean.em = this.em;
}
@Test
public void crud(){
Book book = new Book("1", "Productive Java EE");
this.et.begin();
int initialSize = this.crudServiceBean.findWithNamedQuery(Book.ALL).size();
//... see CRUD Service Example
I only changed one line in the persistence.xml to switch from the embedded to the in-memory mode (Glassfish v2.1 with TopLink):
Embedded mode: <property name="toplink.jdbc.url" value="jdbc:derby:./testDB;create=true"/>
In-Memory mode: <property name="toplink.jdbc.url" value="jdbc:derby:memory:testDB;create=true"/>
In the In-Memory configuration you don't have to drop the tables or clean the database after the tests - it just disappears. You only have to create the tables before the tests. In Glassfish v2 with Toplink you can fall back to the following setting: <property name="toplink.ddl-generation" value="create-tables"/>.
The performance is significantly faster, also in this simple case. The embedded mode took:
Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 2.997 sec
...and the same unit tests on in-memory database:
Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 2.476 sec
H2 and HSQLDB have the in-memory capabilities for ages. Java DB, however, comes with more complete feature-set and is surprisingly DB 2 compatible. The working example was pushed into http://kenai.com/projects/javaee-patterns/ (DAOPattern).
[The code was originally published in this Real World Java EE Patterns book, Page 141]
Just want to promote a small project i newly created to make unittesting JPA and JEE5 EJBs easier:
http://markatta.com/jee5unit
Uses HSQL and Hibernate though.
Posted by Johan Andrén on July 16, 2009 at 01:56 PM CEST #
Adam, I made some performance tests a few weeks ago. You can check http://agoncal.wordpress.com/2009/07/05/derby-10-5-1-1-is-really-an-in-memory-database/
Posted by Antonio Goncalves on July 16, 2009 at 02:08 PM CEST #
Nice! The lack of this feature took me previously to the H2 database system. I'll give JavaDB another look then.
Posted by Jamie on July 16, 2009 at 02:28 PM CEST #
I once tried working with H2 and HSQLDB for unit testing JPA 1.0 code. I create a new numbered .sql script for every commit that changes database DDL so when I check-out a particular revision of code I can build the database as it was at that time. For my tests I would run these scripts and get errors in H2 because it wasn't compatible with all of SQL or possibly Postgres specific things. In the end I decided to have the tests run directly against a postgres server that is dedicated to testing.
I've always been weary of letting the O/R mapper figure out the difference between a database and the model objects, and letting it update the DDL. Maybe I should consider looking at fully describing the schema using JPA annotations and giving it a try so the JPA provider can run on production databases and JavaDB, H2, etc. One issue I foresee is persistence.xml needing to be updated when I change database vendors (production/test) unless it can detect automatically. I think TopLink Essentials detects automatically, I'm not sure about Hibernate.
Posted by Ryan de Laplante on July 16, 2009 at 04:54 PM CEST #
regarding DB2. Apache Derby (-> JavaDB) was donated by IBM to the ASF, so I guess the DB2 stuff is not a big surprise.
Posted by Matthias Wessendorf on July 22, 2009 at 02:00 PM CEST #
@Matthias,
but the quality of the DB 2 support really surprised me. Even some optimizer hints are supported.
Beyond that - Java-Stored procedures are interesting as well,
thanks!,
adam
Posted by Adam Bien on July 22, 2009 at 02:13 PM CEST #
because of different bugs fixed for the in-memory mode you should also look on the upcomming 10.5.2 Release
http://people.apache.org/~kmarsden/derby10.5.2.0.794445/
n.b.: derby has more interesting, but very unknown features (like build in cluster support, xml-datatype and virtual tables) .
Described in my german article in the current database pro magazin 4/2009
Posted by pif on July 27, 2009 at 07:07 PM CEST #
@PIF,
yes, especially the cluster support is interesting.
thanks for the comment!,
adam
Posted by Adam Bien on July 27, 2009 at 08:00 PM CEST #
Hi Adam,
What did you have to do to get your netbeans project to locate the location of your "test" persistence.xml file?
Currently, if I call Persistence from any unit test, I get a failure from toplink saying that there are no persistence provider named test.
Posted by Patrick Julien on October 27, 2009 at 04:51 AM CET #
Acolyte framework is another way of doing so: manage the JDBC connection by yourself during test, to be sure which resultset/update count it returns for each update/query statement. https://github.com/cchantep/acolyte
Posted by applicius on March 01, 2014 at 12:19 PM CET #