JPA 2.1 testing: persisting the pre-loaded data

2019-08-25 09:32发布

问题:

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?