Features¶
Entity Fields that are set automatically¶
For a modeled entity there is a modeling option UtilityFields. When this option is set to true, the generator automatically adds the following properties to an entity:
private Timestamp creationTimestamp;
private Timestamp modificationTimestamp;
private String createdBy;
private String modifiedBy;
The generated lifecycle listeners then take care of calling the related property setters. In order to be able to set the createdBy
and modifiedBy
properties, the lifecycle listener uses the class ThreadLocalSessionData
. Code to set the session data has to be written manually.
JPA Static Metamodel¶
Persistence providers normally come with the functionality to let the static metamodel be generated. You can for instance use a provider specific maven plugin to generate that static metamodel. With the JPA generator you do not need to take care of this extra step. It generates the static metamodel on the fly, along with the entity classes.
Here is an example of a class providing the static metamodel for the entity class Person.java.
/**
* JPA Metamodel description for {@link com.gs.vd.refmodel.persistence.Person}.
*
* Person
*
* @see com.gs.vd.refmodel.persistence.Person
*/
@StaticMetamodel(value=Person.class)
public class Person_ extends BaseEntity_ { // start of class
/**
* JPA Metamodel mapping for {@link com.gs.vd.refmodel.persistence.BaseEntity#getId()}.
*
* @see com.gs.vd.refmodel.persistence.BaseEntity#getId()
*/
public static volatile SingularAttribute<Person, Long> id;
/**
* JPA Metamodel mapping for {@link com.gs.vd.refmodel.persistence.Person#getName()}.
*
* @see com.gs.vd.refmodel.persistence.Person#getName()
*/
public static volatile SingularAttribute<Person, String> name;
...
Testdata Generation¶
There are three generated files that are used to create test data that is directly inserted into a database:
- DataGenerator.java
- TestDataGenerator.java
- TestTestDataGenerator.java
Running TestTestDataGenerator
with JUnit creates several instances of entity classes and uses a JPA persistence provider to insert the data into the database.
You can modify the generated code in TestDataGenerator
to tweak the way the test data is created.
The test data creation process takes rules like non-nullable columns and field lenghts into account. It also ensures that entity objects in collections are persisted successfully.
Testing¶
Classes with JUnit annotations are generated for testing the following types of classes:
- Entity Class
- Entity DAO Class
- Test Data Generator
Tests can be executed by using JPA outside of a JEE application server or with the entity classes deployed in a JEE application server. The latter one is achieved by using the Arquillian framework.
Data Access Objects (DAO)¶
There is one DAO class generated for each entity class. Each DAO class has the following methods:
get()
getAll()
create()
update()
delete()
By using the DAO classes to handle data access, you have one central point where you can tweak the code to handle special cases. Also, you can manually add methods to retrieve filtered data (e.g. by using the JPA Criteria API) and all other classes of your application can reuse those implementations.
Persistence Units¶
In the file persistence.xml, one or more persistence units can be defined with the tag <persistence-unit>
.
The JPA generator always creates two persistence units, one for transaction type JTA
and one for transaction type RESOURCE_LOCAL
.
The one with transaction type JTA
is meant to be used inside a JEE application server while the one with transaction type RESOURCE_LOCAL
is meant to be used for standalone Java applications.
Note
Eclipse shows a warning for a persistence.xml when it contains more than one persistence unit: Multiple persistence units defined - only the first persistence unit will be recognized
. You can safely ignore this warning since JPA itself does not impose that restriction.
When the generator option single-persistence-unit-name
is set, all modeled entities are added to one single persistence unit. However, when single-persistence-unit-name
is set to an empty string, one persistence unit is generated for every modeled persistence module (e.g. for module MyPersistenceModule kind = Persistence;).
Lifecycle Listeners¶
One entity lifecycle listener class is generated for every generated entity class. The implementation of the generated listener classes’ methods is empty, with one exception: When you set modeled entity’s option UtilityFields to true, the lifecycle listener class that corresponds to the generated entity class already has an implementation to set the entity class fields creationTimestamp
,
modificationTimestamp
, createdBy
and modifiedBy
.
Inheritance¶
The Persistence DSL lets you model inheritance relationships between entities. JPA supports the following four inheritance strategies. Only two of them are supported by the generator.
- Mapped Superclass
- Table per Class (not supported)
- Single Table
- Joined (not supported)
Mapped Superclass¶
All parent entities of an entity must have Storable set to false. As a result of this, the generator adds a @MappedSuperclass annotation to the parent entity classes.
There will not be a database table for the entity that has the @MappedSuperclass annotation. Due to this, you can’t use so-called polymorphic queries to get all data records for all child entities in one go. Also, you cannot have entity relations in a @MappedSuperclass. The Persistence DSL does allow to model entity typed fields in a non-storable entity, but the JPA generator will raise an error.
Table per Class¶
Note
This inheritance strategy is not supported by the generator since its resulting database queries might become a performance issue.
Single Table¶
To get this strategy you simply model entities that inherit from each other where the parent entity has Storable set to true (which is the default value). Please be aware of the fact that none of the fields of the leaf entity classes in the inheritance tree can be mandatory fields: The resulting database fields must not have a NOT NULL constraint. However, you can still model the fields as being mandatory. The generator then will provide an implementation in the generated lifecycle listener classes that ensures that the mandatory fields get non-null values assigned. An exception will be thrown otherwise.
Joined¶
Note
This inheritance strategy is not supported by the generator since the Single Table strategy results in easier SQL queries and a better performance.
Primary Keys¶
A primary key field with the annotation @Id
is generated when you set the option Id on an entity field to true.
/**
* BaseEntity (abstract)
*/
entity BaseEntity {
field Id : NumericPrimaryKey {
set Id = true;
}
}
The primary key generation strategy AUTO is used when the primary key field has a numeric type.
...
@Id
@GeneratedValue(generator="baseentity_seq", strategy=GenerationType.AUTO)
@SequenceGenerator(name="baseentity_seq", sequenceName="baseentity_seq", initialValue=1, allocationSize=1)
public Long getId() {
...
Note
While the DSL Persistence allows to model entities with combined primary keys, the JPA
generator does not support this modeling style.
Only single primary key fields per entity class are supported.
Also, in an inheritance relationship the generator allows only one of the entities that inherit from each other to have an id field.
equals()
and hashCode()
¶
Entity fields that are taken into account in equals()
and hashCode()
method implementations should not change their value during the lifetime of an object.
At least properties generated for modeled @Id
fields where the field value is set by the application and not the database, should be used for the generated equals()
and hashCode()
implementation. If you want generated properties
to be taken into account in equals()
and hashCode()
, you have to set a modeled entity field’s boolean option EqualityRelevance to true.