diff --git a/api/src/main/java/jakarta/persistence/EntityManagerFactory.java b/api/src/main/java/jakarta/persistence/EntityManagerFactory.java index 0cc74156..b02ee05e 100644 --- a/api/src/main/java/jakarta/persistence/EntityManagerFactory.java +++ b/api/src/main/java/jakarta/persistence/EntityManagerFactory.java @@ -171,6 +171,17 @@ public interface EntityManagerFactory extends AutoCloseable { */ public PersistenceUnitUtil getPersistenceUnitUtil(); + /** + * Return interface providing access to schema management + * operations for the persistence unit. + * @return SchemaManager interface + * @throws IllegalStateException if the entity manager factory + * has been closed + * + * @since 3.2 + */ + public SchemaManager getSchemaManager(); + /** * Define the query, typed query, or stored procedure query as * a named query such that future query objects can be created diff --git a/api/src/main/java/jakarta/persistence/SchemaManager.java b/api/src/main/java/jakarta/persistence/SchemaManager.java new file mode 100644 index 00000000..081ab94b --- /dev/null +++ b/api/src/main/java/jakarta/persistence/SchemaManager.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2008, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Gavin King - 3.2 + +package jakarta.persistence; + +import java.util.Map; + +/** + * Allows programmatic {@linkplain #create schema creation}, + * {@linkplain #validate schema validation}, + * {@linkplain #truncate data cleanup}, and + * {@linkplain #drop schema cleanup} for entities belonging + * to a certain persistence unit. + * + *

Properties are inherited from the {@link EntityManagerFactory}, + * that is, they may be specified via {@code persistence.xml} or + * {@link Persistence#createEntityManagerFactory(String, Map)}. + * + * @see EntityManagerFactory#getSchemaManager() + * + * @since 3.2 + */ +public interface SchemaManager { + /** + * Create database objects mapped by entities belonging to the + * persistence unit. + * + *

If a DDL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + * + * @param createSchemas if {@code true}, attempt to create schemas, + * otherwise, assume the schemas already exist + */ + void create(boolean createSchemas); + + /** + * Drop database objects mapped by entities belonging to the + * persistence unit, undoing the effects of the + * {@linkplain #create(boolean) previous creation}. + * + *

If a DDL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + * + * @param dropSchemas if {@code true}, drop schemas, + * otherwise, leave them be + */ + void drop(boolean dropSchemas); + + /** + * Validate that the database objects mapped by entities belonging + * to the persistence unit have the expected definitions. + * + *

The persistence provider is not required to perform + * any specific validation, so the semantics of this operation are + * entirely provider-specific. + * + * @throws SchemaValidationException if a database object is missing or + * does not have the expected definition + */ + void validate() throws SchemaValidationException; + + /** + * Truncate the database tables mapped by entities belonging to + * the persistence unit, and then re-import initial data from any + * configured SQL scripts for data loading. + * + *

If a SQL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + */ + void truncate(); +} diff --git a/api/src/main/java/jakarta/persistence/SchemaValidationException.java b/api/src/main/java/jakarta/persistence/SchemaValidationException.java new file mode 100644 index 00000000..69164ef4 --- /dev/null +++ b/api/src/main/java/jakarta/persistence/SchemaValidationException.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Gavin King - 3.2 + +package jakarta.persistence; + +/** + * Thrown when {@link SchemaManager#validate() schema validation} fails. + * + * @see SchemaManager#validate() + * + * @since 3.2 + */ +public class SchemaValidationException extends Exception { + private final Exception[] failures; + + /** + * An array of problems detected while validating the schema. + * + *

A persistence provider might choose to fail fast upon + * encountering a problem with one database object, in which + * case there is only one problem reported here. Alternatively, + * a provider might choose to continue validating the remaining + * database objects, in which case multiple problems might be + * reported, each as a separate exception instance. + */ + public Exception[] getFailures() { + return failures; + } + + /** + * Constructs a new instance with a message and, optionally, + * an array of exceptions, each representing a problem detected + * while validating the schema. + * @param message an overall message + * @param failures an array of exceptions, each representing a + * separate problem + */ + public SchemaValidationException(String message, Exception... failures) { + super(message); + this.failures = failures == null ? new Exception[0] : failures; + } + +} diff --git a/spec/src/main/asciidoc/appendixes.adoc b/spec/src/main/asciidoc/appendixes.adoc index e6ee1c01..c67cd0be 100644 --- a/spec/src/main/asciidoc/appendixes.adoc +++ b/spec/src/main/asciidoc/appendixes.adoc @@ -114,6 +114,8 @@ Added _runInTransaction()_ and _callInTransaction()_ to _EntityManagerFactory_ Added support for specifying null precedence when ordering JPQL and criteria queries +Introduced SchemaManager API + Added _getSingleResultOrNull()_ to _Query_, _TypedQuery_, _StoredProcedureQuery_ Added new operations to _PersistenceUnitUtil_ diff --git a/spec/src/main/asciidoc/ch07-entitymanagers-and-persistence-contexts.adoc b/spec/src/main/asciidoc/ch07-entitymanagers-and-persistence-contexts.adoc index 4f565650..0dc29aec 100644 --- a/spec/src/main/asciidoc/ch07-entitymanagers-and-persistence-contexts.adoc +++ b/spec/src/main/asciidoc/ch07-entitymanagers-and-persistence-contexts.adoc @@ -358,6 +358,17 @@ public interface EntityManagerFactory extends AutoCloseable { */ public PersistenceUnitUtil getPersistenceUnitUtil(); + /** + * Return interface providing access to schema management + * operations for the persistence unit. + * @return SchemaManager interface + * @throws IllegalStateException if the entity manager factory + * has been closed + * + * @since 3.2 + */ + public SchemaManager getSchemaManager(); + /** * Define the query, typed query, or stored procedure query as * a named query such that future query objects can be created @@ -1628,4 +1639,101 @@ public interface PersistenceUnitUtil extends PersistenceUtil { */ public Object getIdentifier(Object entity); } +---- + +=== SchemaManager Interface [[a12178]] + +The _SchemaManager_ interface allows programmatic control over schema +generation and cleanup at runtime. This differs from the functionality +described in <> which allows schema generation before or during +the application deployment and initialization process. Similarly, the +_generateSchema_ method described in <> is intended to be called +before the _EntityManagerFactory_ is available. By contrast, an instance +of _SchemaManager_ is only available after an _EntityManagerFactory_ has +already been created. + +For example, _SchemaManager_ is especially useful in tests. + +The methods of _SchemaManager_ correspond to values of the property +_jakarta.persistence.schema-generation.scripts.action_. The methods +_create()_, _drop()_, and _validate()_ correspond to the actions +_create_, _drop_, and _validate_. The method _truncate()_ has no +corresponding action. + +Thus, the behavior of the _SchemaManager_ may be controlled via the +properties defined in <> and <>. + +[source,java] +---- +package jakarta.persistence; + +import java.util.Map; + +/** + * Allows programmatic {@linkplain #create schema creation}, + * {@linkplain #validate schema validation}, + * {@linkplain #truncate data cleanup}, and + * {@linkplain #drop schema cleanup} for entities belonging + * to a certain persistence unit. + * + *

Properties are inherited from the {@link EntityManagerFactory}, + * that is, they may be specified via {@code persistence.xml} or + * {@link Persistence#createEntityManagerFactory(String, Map)}. + * + * @see EntityManagerFactory#getSchemaManager() + * + * @since 3.2 + */ +public interface SchemaManager { + /** + * Create database objects mapped by entities belonging to the + * persistence unit. + * + *

If a DDL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + * + * @param createSchemas if {@code true}, attempt to create schemas, + * otherwise, assume the schemas already exist + */ + void create(boolean createSchemas); + + /** + * Drop database objects mapped by entities belonging to the + * persistence unit, undoing the effects of the + * {@linkplain #create(boolean) previous creation}. + * + *

If a DDL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + * + * @param dropSchemas if {@code true}, drop schemas, + * otherwise, leave them be + */ + void drop(boolean dropSchemas); + + /** + * Validate that the database objects mapped by entities belonging + * to the persistence unit have the expected definitions. + * + *

The persistence provider is not required to perform + * any specific validation, so the semantics of this operation are + * entirely provider-specific. + * + * @throws SchemaValidationException if a database object is missing or + * does not have the expected definition + */ + void validate() throws SchemaValidationException; + + /** + * Truncate the database tables mapped by entities belonging to + * the persistence unit, and then re-import initial data from any + * configured SQL scripts for data loading. + * + *

If a SQL operation fails, the behavior is undefined. + * A provider may throw an exception, or it may ignore the problem + * and continue. + */ + void truncate(); +} ---- \ No newline at end of file diff --git a/spec/src/main/asciidoc/ch08-entity-packaging.adoc b/spec/src/main/asciidoc/ch08-entity-packaging.adoc index 3ffaa887..89047810 100644 --- a/spec/src/main/asciidoc/ch08-entity-packaging.adoc +++ b/spec/src/main/asciidoc/ch08-entity-packaging.adoc @@ -526,8 +526,8 @@ properties used in the _persistence.xml_ file. The _jakarta.persistence.schema-generation.database.action_ property specifies the action to be taken by the persistence provider with regard to the database artifacts. The values for this property are _none_, _create_, -_drop-and-create_, _drop_. If this property is not specified, it is -assumed that schema generation is not needed or will be initiated by +_drop-and-create_, _drop_, _validate_. If this property is not specified, +it is assumed that schema generation is not needed or will be initiated by other means, and, by default, no schema generation actions will be taken on the database. (See <>.) * _jakarta.persistence.schema-generation.scripts.action_ + diff --git a/spec/src/main/asciidoc/ch09-container-provider-contracts.adoc b/spec/src/main/asciidoc/ch09-container-provider-contracts.adoc index ed2525b9..951d285f 100644 --- a/spec/src/main/asciidoc/ch09-container-provider-contracts.adoc +++ b/spec/src/main/asciidoc/ch09-container-provider-contracts.adoc @@ -139,7 +139,7 @@ If a provider does not qualify as the provider for the named persistence unit, it must return _null_ when _createEntityManagerFactory_ is invoked on it. -==== Schema Generation +==== Schema Generation [[a12803]] In Java SE environments, the _Persistence.generateSchema_ method may be used by the application to @@ -389,7 +389,7 @@ deploying the persistence unit The _jakarta.persistence.schema-generation.database.action_ property specifies the action to be taken by the persistence provider with regard to the database artifacts. The values for this property are _"none"_, -_"create"_, _"drop-and-create"_, _"drop"_. If the +_"create"_, _"drop-and-create"_, _"drop"_, _"validate"_. If the _jakarta.persistence.schema-generation.database.action_ property is not specified, no schema generation actions must be taken on the database. * _jakarta.persistence.schema-generation.scripts.action_ +