users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: schema generation proposed changes

From: Steve Ebersole <steve.ebersole_at_redhat.com>
Date: Thu, 30 Aug 2012 22:04:35 -0500

Well a real simple example is that Derby supports sequences after 10.6,
but not before. So there DatabaseMetaData#getDatabaseMajorVersion=10
and DatabaseMetaData#getDatabaseMinorVersion=6. Even if the Derby
driver were to report the
DatabaseMetaData#getDatabaseProductVersion="10.6" or somesuch, relying
on being able to parse that into ints to be able to do range checks
make me nervous, especially when JDBC already offers means to know the
major/minor.

And thats just one example that came to me immediately.

On Thu 30 Aug 2012 07:24:45 PM CDT, Linda DeMichiel wrote:
> Hi Steve,
>
> I'd like to understand this better, as the info I have from our team here
> indicates that database produce name together with version (in the
> worst case)
> would be sufficient. Do we need all four properties to accommodate
> the range
> of drivers/databases?
>
> thanks,
>
> -Linda
>
>
> On 8/29/2012 7:30 AM, Steve Ebersole wrote:
>> As far as:
>>
>> javax.persistence.database-product-name,
>> javax.persistence.database-product-version,
>>
>> I'd really rather see major/minor version used:
>>
>> (int) java.sql.DatabaseMetaData#getDatabaseMajorVersion
>> (int) java.sql.DatabaseMetaData#getDatabaseMinorVersion
>>
>> as opposed to the proposed:
>>
>> (String) java.sql.DatabaseMetaData#getDatabaseProductVersion
>>
>> For one Hibernate already uses those 2 ;) For another its more
>> indicative of what is/isn't available consistently across
>> databases.
>>
>>
>> On 07/23/2012 06:55 PM, Linda DeMichiel wrote:
>>> Here's an updated version of my earlier schema generation proposal,
>>> broken out as to proposed spec changes. You should hopefully find
>>> this considerably more flexible and detailed than the earlier draft.
>>>
>>> -Linda
>>>
>>> ----------------------------
>>>
>>> Proposed spec changes:
>>>
>>>
>>> New Section: Schema Generation [to follow section 9.3]
>>>
>>> Schema generation may either happen prior to application deployment or
>>> when the entity manager factory is created as part of the application
>>> deployment and initialization process.
>>>
>>> * In Java EE environments, the container may call the
>>> PersistenceProvider generateSchema method separately from and/or
>>> prior to the creation of the entity manager factory for the
>>> persistence unit, or the container may pass additional
>>> information to the createContainerEntityManagerFactory call to
>>> cause schema generation to happen as part of the entity manager
>>> factory creation and application initialization process. The
>>> information passed to these methods determines whether the
>>> generation of schemas and/or tables occurs directly in the target
>>> database, or whether DDL scripts for schema generation are
>>> created, or both.
>>>
>>> * In Java SE environments, the application may call the Persistence
>>> generateSchema method separately from and/or prior to the creation
>>> of the entity manager factory or may pass information to the
>>> createEntityManagerFactory method to cause schema generation to
>>> occur as part of the entity manager factory creation.
>>>
>>>
>>> The application may provide DDL scripts to be used for schema
>>> generation, and package these scripts as part of the persistence unit
>>> or specify URLs corresponding to the location of such scripts. In
>>> Java EE environments, such scripts may be executed by the container,
>>> or the container may direct the persistence provider to execute the
>>> scripts; in Java SE environments, the execution of the scripts is the
>>> responsibility of the persistence provider. In the absence of the
>>> specification of scripts, schema generation, if requested, will be
>>> determined by the object/relational metadata of the persistence unit.
>>>
>>>
>>> The following standard properties are defined for use in schema
>>> generation. In Java EE environments these properties are passed by
>>> the container in the Map argument to the PersistenceProvider
>>> generateSchema method or createContainerEntityManagerFactory method.
>>> In Java SE environments, they are passed in the Map argument to the
>>> Persistence generateSchema or createEntityManagerFactory method.
>>>
>>>
>>> javax.persistence.schema-generation-target:
>>>
>>> The schema-generation-target property specifies whether the schema
>>> is to be created in the database, whether scripts are to be
>>> generated, or both.
>>>
>>> values for this property: DATABASE, SCRIPTS, DATABASE_AND_SCRIPTS
>>> [Open Issue: introduce for these enum or use strings? Better names??]
>>>
>>>
>>> javax.persistence.schema-generation-action:
>>>
>>> The schema-generation-action property is used to specify the action
>>> to be taken by the persistence provider. If the
>>> schema-generation-target property is not specified, no action must
>>> be taken.
>>>
>>> values for this property: NONE, CREATE, DROP_AND_CREATE, DROP
>>> [Open Issue: enum strings ("none", "create", "drop-and-create",...)
>>>
>>>
>>> javax.persistence.create-database-schemas
>>>
>>> In Java EE environments, it is anticipated that the Java EE
>>> platform provider may wish to control the creation of database
>>> schemas rather than delegate this task to the persistence provider.
>>> The create-database-schemas property specifies whether the
>>> persistence provider is to create the database schema(s) in
>>> addition to creating database objects such as tables, sequences,
>>> constraints, etc. The value of this boolean property should be set
>>> to true if the persistence provider is to create schemas in the
>>> database or to generate DDL which is to contain "CREATE SCHEMA"
>>> commands. If this property is not supplied, the provider should
>>> not attempt to create database schemas. This property may be
>>> specified in Java SE environments as well.
>>>
>>>
>>> javax.persistence.ddl-create-script-target,
>>> javax.persistence.ddl-drop-script-target:
>>>
>>> If scripts are to be generated, the target locations for the
>>> writing of these scripts must be specified. These targets may take
>>> the form of either Writers or strings designating URLs. The
>>> persistence provider must produce both create and drop scripts if
>>> the corresponding DDL targets are specified. This is independent
>>> of whether a drop action is included in the value passed for the
>>> schema-generation-action property. If the schema-generation-target
>>> property specifies scripts and script targets are not specified,
>>> the IllegalArgumentException should be thrown by the provider.
>>>
>>> ddl-create-script-target: a Writer configured for the persistence
>>> provider for output of the DDL script or a string specifying
>>> the URL for the DDL script. This property should only be
>>> specified if scripts are to be generated.
>>>
>>> ddl-drop-script-target: a Writer configured for the persistence
>>> provider for output of the DDL script or a string specifying the
>>> URL for the DDL script. This property should only be specified
>>> if scripts are to be generated.
>>> [Suggestions for better names ??]
>>>
>>>
>>> javax.persistence.database-product-name,
>>> javax.persistence.database-product-version,
>>>
>>> If scripts are to be generated by the persistence provider and a
>>> connection to the target database is not supplied, the
>>> javax.persistence.database-product-name property must be
>>> specified. The value of this property should be the value
>>> returned for the target database by the JDBC DatabaseMetaData
>>> method getDatabaseProductName. If sufficient database version
>>> information is not included in the result of this method, the
>>> database-product-version property should also be specified, and
>>> should contain the value returned by the JDBC
>>> getDatabaseProductVersion method.
>>>
>>>
>>>
>>> javax.persistence.ddl-create-script-source,
>>> javax.persistence.ddl-drop-script-source:
>>>
>>> The ddl-create-script-source and ddl-drop-script-source properties
>>> are used for script execution. In Java EE container environments,
>>> it is generally expected that the container will be responsible
>>> for executing DDL scripts, although the container is permitted to
>>> delegate this task to the persistence provider. If DDL scripts
>>> are to be used in Java SE environments or if the Java EE container
>>> delegates the execution of scripts to the persistence provider,
>>> these properties must be specified. The script sources may take
>>> the form of either Readers or strings designating URLs.
>>>
>>> ddl-create-script-source: a Reader configured for reading of the
>>> DDL script or a string specifying the URL for the DDL script.
>>>
>>> ddl-drop-script-source: a Reader configured for reading of the DDL
>>> script or a string specifying the URL for the DDL script.
>>> [Suggestions for better names ??]
>>>
>>>
>>>
>>> javax.persistence.sql-load-script-source:
>>>
>>> A data load script may be supplied as part of the persistence
>>> unit. In Java EE container environments, it is generally expected
>>> that the container will be responsible for executing data load
>>> scripts, although the container is permitted to delegate this task
>>> to the persistence provider. If a load script is to be used in
>>> Java SE environments or if the Java EE container delegates the
>>> execution of the load script to the persistence provider, this
>>> property must be specified. The script source may take the form
>>> of either a Reader or a string designating a URL.
>>>
>>> sql-load-script-source: a Reader configured for reading of the SQL
>>> load script for database initialization or a string specifying
>>> the URL for the script.
>>>
>>>
>>>
>>> javax.persistence.schema-generation-connection:
>>>
>>> JDBC connection to be used for schema generation. This is intended
>>> for use in Java EE environments, where the platform provider may
>>> want to control the database privileges that are available to the
>>> persistence provider. This connection is provided by the container,
>>> and should be closed by the container when the schema generation
>>> request or entity manager factory creation completes. The
>>> connection provided must have credentials sufficient for the
>>> persistence provider to carry out the requested actions. If this
>>> property is not specified, the persistence provider should use the
>>> DataSource that has otherwise been provided.
>>>
>>>
>>>
>>> 9.4.1 PersistenceProvider Interface:
>>>
>>> New method:
>>>
>>> /**
>>> * Create database schemas and/or tables and/or create DDL
>>> * scripts as determined by the supplied properties
>>> *
>>> * @param info metadata for use by the persistence provider
>>> * @param map properties for schema generation; these
>>> * may also contain provider-specific properties
>>> * @throws PersistenceException if insufficient or inconsistent
>>> * configuration information is provided or if schema
>>> * generation otherwise fails.
>>> */
>>> public void generateSchema(PersistenceUnitInfo info, Map map)
>>>
>>>
>>> 9.6 Persistence Class
>>>
>>> New method:
>>>
>>> /**
>>> * Create database schemas and/or tables and/or create DDL
>>> * scripts as determined by the supplied properties
>>> *
>>> * @param persistenceUnitName the name of the persistence unit
>>> * @param map properties for schema generation; these may also
>>> * contain provider-specific properties. The values of
>>> * these properties override any values that may have been
>>> * configured elsewhere.
>>> * @throws PersistenceException if insufficient or inconsistent
>>> * configuration information is provided or if schema
>>> * generation otherwise fails.
>>> */
>>> public void generateSchema(String persistenceUnitName, Map properties)
>>>
>>>
>>> -----------------------
>>>
>>> Section 8.2.1 persistence.xml file
>>>
>>> To be added to section 8.2.1:
>>>
>>> Scripts for use in schema generation and bulk loading of data may be
>>> packaged as part of the persistence unit.
>>>
>>>
>>> To be added to Section 8.2.1.9 (properties):
>>>
>>> Scripts for use in schema generation are specified using the
>>> ddl-create-script and ddl-drop-script elements. A script to specify
>>> SQL for the bulk loading of data may be specified by the
>>> sql-load-script element. These scripts may be packaged as part of the
>>> persistence unit or designated by URL strings.
>>>
>>> <xsd:element name="database-scripts" type="database-scripts-type"
>>> minOccurs="0"/>
>>>
>>> <xsd:complexType name="database-scripts-type">
>>> <xsd:sequence>
>>> <xsd:element name="ddl-create-script" type="xsd:string"/>
>>> <xsd:element name="ddl-drop-script" type="xsd:string" minOccurs="0"/>
>>> <xsd:element name="sql-load-script" type="xsd:string" minOccurs="0"/>
>>> </xsd:sequence>
>>> </xsd:complexType>
>>>
>>> [Open Issue: do we want to require a drop-script if a create-script
>>> has been provided?]
>>>
>>> -----------
>>>
>>> Chapter 11:
>>>
>>> New annotations for use in schema generation:
>>>
>>> @Target({}) @Retention(RUNTIME)
>>> public @interface Index {
>>> String name() default "";
>>> String columnList();
>>> boolean unique() default false; // should this be here or just use
>>> UniqueConstraints?
>>> }
>>>
>>> columnList syntax follows that of the OrderBy annotation:
>>>
>>> columnList::= indexColumn [, indexColumn]*
>>> indexColumn::= columnName [ASC | DESC]
>>>
>>> If ASC or DESC is not specified, ASC is assumed
>>>
>>> Index[] indexes() default {};
>>> is to be added to Table, SecondaryTable, CollectionTable, JoinTable,
>>> and
>>> TableGenerator
>>>
>>>
>>>
>>> /**
>>> * Provides for defining a foreign key constraint or for overriding
>>> * or disabling the persistence provider's default foreign key
>>> * definition.
>>> */
>>> @Target({}) @Retention(RUNTIME)
>>> public @interface ForeignKey {
>>> String name() default "";
>>> String foreignKeyDefinition() default "";
>>> boolean disableForeignKey() default false;
>>> }
>>>
>>>
>>> The syntax used in the foreignKeyDefinition element should follow the
>>> SQL syntax used by the target database for foreign key constraints.
>>> E.g., this would likely be similar to the following:
>>>
>>> FOREIGN KEY ( <COLUMN expression> {, <COLUMN expression>}... )
>>> REFERENCES <TABLE identifier> [ ( <COLUMN expression> {, <COLUMN
>>> expression>}... ) ]
>>> [ ON UPDATE <referential action> ]
>>> [ ON DELETE <referential action> ]
>>>
>>> If disableForeignKey is specified as true, the provider must not
>>> generate
>>> a foreign key constraint.
>>>
>>>
>>> The following is to be added to JoinColumn, JoinColumns,
>>> MapKeyJoinColumn,
>>> MapKeyJoinColumns, PrimaryKeyJoinColumn and PrimaryKeyJoinColumns:
>>>
>>> ForeignKey foreignKey() default @ForeignKey();
>>>
>>>