JPA Manual
Short manual on how to use JPA in your Molgenis application.
JPA documentation
For extensive documentation on JPA see the official JPA Tutorial at Sun/Oracle site.
Usage of JPA within Molgenis
In order to use JPA in your Molgenis project, you have to enable it in the properties file:
mapper_implementation = JPA
Note: The value 'JPA' is case-sensitive.
By default mysql is used as database backend. If you want to change this edit you're project properties file. Make sure to add the database Driver in to the classpath!
db_driver = oracle.jdbc.driver.OracleDriver hibernate_dialect = Oracle10gDialect
After generating your Molgenis application the following files are JPA related:
- generated/java/META-INF/persistence.xml
- generated/java/packagename/db/EntitynameJpaMapper.java
- app/JpaDatabase.java
The default JPA enabled molgenis uses Hibernate (3.6.x).
DatabaseFactory AND persistence.xml
All information regarding the configuration of JPA can be found in persistence.xml. The file defines one persistence units, "molgenis". To create a JPA enabled Database it's recommended to use DatabaseFactory.create() method.
It's possible to change of course the generated persistence.xml. For information about configuration options see Hibernate Core Reference Manual (Chapter 3) & Hibernate EntityManager User Guide (Chapter 2). To prevent molgenis from overwriting you persistence.xml (usefull when made change to the persistence.xml) when generating use the following option in properties file: generate_persistence = false.
To change JPA configuration in code use the DatabaseFactory.create(Map<String, Object> configOverwrites). For example the test use the following code:
Map<String, Object> configOverrides = new HashMap<String, Object>();
configOverrides.put("javax.persistence.jdbc.url", "${options.dbUri}_test");
configOverrides.put("hibernate.hbm2ddl.auto", "create-drop");
DatabaseFactory.create(configOverrides);
Logging
Hibernate uses log4j as logging framework. This enables you to fine tune the log4j.properties file to log everything you need to know. But wait there are a couple of options that can be enabled really quickly that makes life easy while debugging your application. This can be done in the persistence.xml or by using configOverwrites.
<property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/>
Database Mappers and EntityManager
Molgenis creates a database access class for you which extends the Database interface. The database class is called JpaDatabase. The interface is the same as for JDBCDatabase but adds one method getEntityManager() which can be used to access JPA features directly. It is strongly recommended to read the JPA documentation mentioned above as well as the book "Pro JPA 2: Mastering the Java(TM) Persistence API (Expert's Voice in Java Technology)".
Primary Key generation
Jpa has many options to generate primary keys for entities that are stored (persisted) in the database. By default molgenis uses the AUTO, which is in most cases sufficient. But if you want to use sequence (Oracle, PostgreSQL) this can be enabled by changing the properties file of you're project:
jpa_use_sequence = true
Every time hibernate inserts a record into the database with use sequence as primary key a roundtrip to the database is made to retrive the new sequence. This can be time consuming. But wait there is a solution, in the database model it's possible to add allocationSize, for example:
<entity name="seqAllocationEntity"> <field name="id" type="autoid" description="automatically generated id" allocationSize="1000" /> <field name="test"> </entity>
Of course this only works when sequence are enabled!
Cascade Rules
To fine tune how the EntityManager? handles relations in certain situation one can use the Cascade rules. This can be uses in the database, for example:
<entity name="Person">
...
<field name="car" type="xref" xref_entity="Car" nillable="true"
jpaCascade="javax.persistence.CascadeType.REMOVE, javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REFRESH, javax.persistence.CascadeType.MERGE"/>
</entity>
Now a Person really own a Car.
- PERSIST: make sure that Car is also persisted in database when Person is stored.
- REMOVE: car is removed from database if person is deleted!
- REFRESH: sometimes entities are reloaded from database by the EntityManager?. If Person is reloaded that car will be reloaded as well.
- MERGE: used when object that are already managed are persisted in database are changed (updated). This means that if Person is updated/changed that the changes in Car (if any are) are also stored in database.
Of course it's possible to ommit or use all Cascade properties as you need. Pro JPA 2 Mastering the Java™ Persistence API Describes Cascade rules and also how the EntityManager works in detail.
Decorators and EntityListeners
Decorators used by the Molgenis framework still work in the same way as long as the methods of the Database interface are used. However, with JPA it is recommended to used annotations and EntityListeners. A proper connection of these concepts to the Molgenis system should be part of the next sprint.
Helper
Sometimes it can be usefull to drop tables in a database and/or recreate them. This can be useful for example in (unit) testing. To do this you can use the org.molgenis.framework.db.jpa.JpaUtil class.