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. The development in
EclipseLink is tracked here.
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.