JPA 2.1 Schema Generation (TOTD #187)
- by arungupta
This blog explained
some of the key
features of JPA 2.1 earlier. Since then Schema Generation has
been added to JPA 2.1. This Tip Of The Day
(TOTD) will provide more details about this new feature in JPA 2.1.
Schema Generation refers to generation of database artifacts like
tables, indexes, and constraints in a database schema. It may or may
not involve generation of a proper database schema depending upon
the credentials and authorization of the user. This helps in
prototyping of your application where the required artifacts are
generated either prior to application deployment or as part of
EntityManagerFactory creation. This is also useful in environments
that require provisioning database on demand, e.g. in a cloud.
This feature will allow your JPA domain object model to be directly
generated in a database. The generated schema may need to be tuned
for actual production environment. This usecase is supported by
allowing the schema generation to occur into DDL scripts which can
then be further tuned by a DBA.
The following set of properties in persistence.xml or specified
during EntityManagerFactory creation controls the behaviour of
schema generation.
Property Name
Purpose
Values
javax.persistence.schema-generation-action
Controls action to be taken by persistence
provider
"none", "create", "drop-and-create", "drop"
javax.persistence.schema-generation-target
Controls whehter schema to be created in
database, whether DDL scripts are to be created, or both
"database", "scripts", "database-and-scripts"
javax.persistence.ddl-create-script-target,
javax.persistence.ddl-drop-script-target
Controls target locations for writing of
scripts. Writers are pre-configured for the persistence
provider. Need to be specified only if scripts are to be
generated.
java.io.Writer (e.g. MyWriter.class) or URL
strings
javax.persistence.ddl-create-script-source,
javax.persistence.ddl-drop-script-source
Specifies locations from which DDL scripts
are to be read. Readers are pre-configured for the
persistence provider.
java.io.Reader (e.g. MyReader.class) or URL
strings
javax.persistence.sql-load-script-source
Specifies location of SQL bulk load script.
java.io.Reader (e.g. MyReader.class) or URL
string
javax.persistence.schema-generation-connection
JDBC connection to be used for schema
generation
javax.persistence.database-product-name,
javax.persistence.database-major-version,
javax.persistence.database-minor-version
Needed if scripts are to be generated and no
connection to target database. Values are those obtained
from JDBC DatabaseMetaData.
javax.persistence.create-database-schemas
Whether Persistence Provider need to create
schema in addition to creating database objects such as
tables, sequences, constraints, etc.
"true", "false"
Section 11.2 in the JPA
2.1 specification defines the annotations used for schema
generation process. For example, @Table, @Column, @CollectionTable,
@JoinTable, @JoinColumn, are used to define the generated schema.
Several layers of defaulting may be involved. For example, the table
name is defaulted from entity name and entity name (which can be
specified explicitly as well) is defaulted from the class name.
However annotations may be used to override or customize the values.
The following entity class:
@Entity public class Employee { @Id private int id; private String name;
. . .
@ManyToOne
private Department dept;
}
is generated in the database with the following attributes:
Maps to EMPLOYEE table in default schema
"id" field is mapped to ID column as primary key
"name" is mapped to NAME column with a default VARCHAR(255).
The length of this field can be easily tuned using @Column.
@ManyToOne is mapped to DEPT_ID foreign key column. Can be
customized using JOIN_COLUMN.
In addition to these properties, couple of new annotations are
added to JPA 2.1:
@Index - An index for the primary key is generated by default
in a database. This new annotation will allow to define
additional indexes, over a single or multiple columns, for a
better performance. This is specified as part of @Table,
@SecondaryTable, @CollectionTable, @JoinTable, and
@TableGenerator. For example:
@Table(indexes = {@Index(columnList="NAME"), @Index(columnList="DEPT_ID DESC")})@Entity public class Employee { . . .}
The generated table will have a default index on the primary
key. In addition, two new indexes are defined on the NAME column
(default ascending) and the foreign key that maps to the
department in descending order.
@ForeignKey - It is used to define foreign key constraint or
to otherwise override or disable the persistence provider's
default foreign key definition. Can be specified as part of
JoinColumn(s), MapKeyJoinColumn(s), PrimaryKeyJoinColumn(s). For
example:
@Entity public class Employee { @Id private int id; private String name; @ManyToOne @JoinColumn(foreignKey=@ForeignKey(foreignKeyDefinition="FOREIGN KEY (MANAGER_ID) REFERENCES MANAGER")) private Manager manager;
. . .
}
In this entity, the employee's manager is mapped by MANAGER_ID
column in the MANAGER table. The value of foreignKeyDefinition
would be a database specific string.
A complete replay of Linda's talk at JavaOne 2012 can be seen
here (click on CON4212_mp4_4212_001 in Media).
These features will be available in GlassFish
4 promoted builds in the near future.
JPA 2.1 will be delivered as part of Java EE 7. The different
components in the Java EE 7 platform are tracked
here.
JPA 2.1 Expert Group has released Early
Draft 2 of the specification. Section 9.4 and 11.2 provide
all details about Schema Generation. The latest javadocs can be
obtained from
here. And the JPA EG would appreciate
feedback.