H2 Pure Java Database

H2 Performance Summary

The following charts show the performance of H2 (in green) relatively to other JPA/DBMS combinations (in gray).

Position #1 on the X-Axis (the fastest) is about 100 times faster than position #32 (the slowest).
In the chart below the Y-Axis represents result score (maximum 100) in logarithmic scale - higher is better:
JPA performance benchmark comparision Hibernate, EclipseLink, OpenJPA, DataNucleus, ObjectDB
In the chart below the Y-Axis represents result score (maximum 100) in linear scale - higher is better:
JPA performance benchmark comparision Hibernate, EclipseLink, OpenJPA, DataNucleus, ObjectDB


The configurations in which H2 has been tested are listed in the following table:

 Database + JPA ProviderNormalized Score
100 - Best,  0 - Worst
Final Position
1 - Best,  32 - Worst
Failed Tests
1EclipseLink with H2 embedded16.43  (out of 32)2
2Hibernate with H2 embedded10.79  (out of 32)0
3OpenJPA with H2 embedded10.111  (out of 32)0
4DataNucleus with H2 embedded5.122  (out of 32)5
5Hibernate with H2 server3.425  (out of 32)0
6EclipseLink with H2 server3.326  (out of 32)2
7OpenJPA with H2 server3.028  (out of 32)0
8DataNucleus with H2 server1.332  (out of 32)7

As shown above, the performance and stability are highly dependent on the JPA provider. H2 is faster and more stable
(in both client-server and embedded modes) when used with EclipseLink or Hibernate.

About H2 Database

H2 Database is a popular pure Java RDBMS. Its first version was released in 2005.

H2 is available under a modified version of the Mozilla Public License (MPL) license or under the Eclipse Public License (EPL).

In this benchmark H2 version 1.2.147 (which was released in 2010) has been tested.

Both client-server and embedded mode are supported by H2 and were tested in this benchmark.

Solved Problems and Issues

The stack traces below demonstrate some exceptions that have been thrown when using H2 database in previous runs of this benchmark and have been fixed by upgrading software and setting.

org.apache.openjpa.persistence.RollbackException: Unique index or primary key violation: "PRIMARY_KEY_2C ON PUBLIC.OPENJPA_SEQUENCES_TABLE(ID)"; SQL statement:
INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [23001-141] {prepstmnt 28057122 INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [params=(String) DEFAULT, (int) 0]} [code=23001, state=23001]
	at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:583)
	at org.jpab.Test.persist(Test.java:216)
	at org.jpab.Test.persist(Test.java:199)
	at org.jpab.Runner$PersistAction.run0(Runner.java:528)
	at org.jpab.Runner$TestAction.run(Runner.java:507)
	at java.lang.Thread.run(Thread.java:619)
Caused by:  org.apache.openjpa.persistence.EntityExistsException: Unique index or primary key violation: "PRIMARY_KEY_2C ON PUBLIC.OPENJPA_SEQUENCES_TABLE(ID)"; SQL statement:
INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [23001-141] {prepstmnt 28057122 INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [params=(String) DEFAULT, (int) 0]} [code=23001, state=23001]
	at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4812)
	at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4787)
	at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:136)
	at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:110)
	at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:62)
	at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:66)
	at org.apache.openjpa.util.ImplHelper.generateValue(ImplHelper.java:160)
	at org.apache.openjpa.util.ImplHelper.generateFieldValue(ImplHelper.java:144)
	at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignField(JDBCStoreManager.java:794)
	at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:487)
	at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:463)
	at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignObjectId(JDBCStoreManager.java:778)
	at org.apache.openjpa.kernel.DelegatingStoreManager.assignObjectId(DelegatingStoreManager.java:135)
	at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:605)
	at org.apache.openjpa.kernel.StateManagerImpl.preFlush(StateManagerImpl.java:2952)
	at org.apache.openjpa.kernel.PNewState.beforeFlush(PNewState.java:40)
	at org.apache.openjpa.kernel.StateManagerImpl.beforeFlush(StateManagerImpl.java:1047)
	at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2077)
	at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2037)
	at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:1955)
	at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
	at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1479)
	at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:925)
	at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:559)
	... 5 more
Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: Unique index or primary key violation: "PRIMARY_KEY_2C ON PUBLIC.OPENJPA_SEQUENCES_TABLE(ID)"; SQL statement:
INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [23001-141] {prepstmnt 28057122 INSERT INTO OPENJPA_SEQUENCES_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [params=(String) DEFAULT, (int) 0]} [code=23001, state=23001]
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:257)
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:233)
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.access$1000(LoggingConnectionDecorator.java:70)
	at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:1079)
	at org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:285)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.executeUpdate(TableJDBCSeq.java:816)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.insertSequence(TableJDBCSeq.java:501)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.access$100(TableJDBCSeq.java:74)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq$AllocateSequenceRunnable.run(TableJDBCSeq.java:902)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.allocateSequence(TableJDBCSeq.java:454)
	at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.nextInternal(TableJDBCSeq.java:305)
	at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:60)
	... 23 more
org.apache.openjpa.persistence.ArgumentException: Failed to execute query "SELECT o FROM Person o WHERE o.lastName LIKE :pattern". Check the query syntax for correctness. See nested exception for details.
	at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:870)
	at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:792)
	at org.apache.openjpa.kernel.DelegatingQuery.execute(DelegatingQuery.java:542)
	at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:288)
	at org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:302)
	at org.jpab.Test.query(Test.java:314)
	at org.jpab.Runner$QueryAction.run0(Runner.java:552)
	at org.jpab.Runner$TestAction.run(Runner.java:507)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at org.apache.openjpa.jdbc.kernel.PreparedSQLStoreQuery$PreparedSQLExecutor.toParameterArray(PreparedSQLStoreQuery.java:157)
	at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:855)
	... 8 more