I'm testing my JPA classes using Arquillian against "remote" containers (Glassfish 4 and WildFly 10, to be specific). I want to:
- Generate the database schema from the JPA entities' definitions (as opposed to SQL scripts).
- Pre-load some data to imitate "the data that was already there". For a most trivial example, to test if I can remove an entity without creating it in the same test first.
- Be able to perform queries, inserts, updates, deletes, etc.
There are javax.persistence.* properties that seem to fit the bill, so one might assume, that the following will work:
<persistence-unit name="test">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/H2DS</jta-data-source>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.sql-load-script-source" value="META-INF/sql/load_script.sql"/>
<property name="javax.persistence.schema-generation.drop-source" value="script"/>
<property name="javax.persistence.schema-generation.drop-script-source" value="META-INF/sql/drop.sql" />
</properties>
Well, not quite.
If one uses a GenerationType.TABLE, then one must update the values for the primary key sequences along with inserting new entities using an SQL script. The problem is that though a few entities are inserted using script (the primary key value in "generator-table" is also updated, of course), the JPA provider does not update its preallocated IDs in any way. So, what happens, as much as I can judge from the logs, is:
- the "generator-table" is created
- the primary keys 1-5 are pre-allocated (but the value in DB table is not updated
- Three entries from script are inserted (but, again, this is not committed yet)
- select and update statements for "generator-table" are prepared (but not executed yet)
- insert statement for an entity instance from the test is prepared, and a wrong primary key is assigned. "Wrong" is -1 in case of Hibernate, and 1 in case of EclipseLink. The latter throws exception because of duplicate entry, of course.
Solutions found so far
EclipseLink: works, if both DB schema and data pre-loading are done with scripts. Suboptimal for the development stage, as one has to fiddle with SQL scripts often.
Hibernate: works, if the following implementation-specific option is set:
<property name="hibernate.id.new_generator_mappings" value="false"/>
That allows to persist an entity from test, the primary key being 3 times the allocation size (15, with 3 entities).
Now, to the question: is there some "standard JPA", implementation-independent way to achieve my requirements as listed in the beginning of this question? They do not seem extravagant at all, so there should be existing solutions, right?