diff --git a/api/src/main/java/jakarta/persistence/Persistence.java b/api/src/main/java/jakarta/persistence/Persistence.java index 510ebf9b..cba96030 100644 --- a/api/src/main/java/jakarta/persistence/Persistence.java +++ b/api/src/main/java/jakarta/persistence/Persistence.java @@ -88,6 +88,36 @@ public static EntityManagerFactory createEntityManagerFactory(String persistence return emf; } + /** + * Create and return an EntityManagerFactory for the named persistence unit + * using the given properties. + * + * @param configuration + * configuration of the persistence unit + * @return the factory that creates EntityManagers configured according to + * the specified persistence unit. + * + * @since 3.2 + */ + public static EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration configuration) { + + EntityManagerFactory emf = null; + PersistenceProviderResolver resolver = PersistenceProviderResolverHolder.getPersistenceProviderResolver(); + + List providers = resolver.getPersistenceProviders(); + + for (PersistenceProvider provider : providers) { + emf = provider.createEntityManagerFactory(configuration); + if (emf != null) { + break; + } + } + if (emf == null) { + throw new PersistenceException("No Persistence provider for EntityManager named " + configuration.name()); + } + return emf; + } + /** * Create database schemas and/or tables and/or create DDL diff --git a/api/src/main/java/jakarta/persistence/PersistenceConfiguration.java b/api/src/main/java/jakarta/persistence/PersistenceConfiguration.java new file mode 100644 index 00000000..672c2b32 --- /dev/null +++ b/api/src/main/java/jakarta/persistence/PersistenceConfiguration.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2008, 2020 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 javax.sql.DataSource; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a configuration of a persistence unit, allowing programmatic + * creation of an {@link EntityManagerFactory}. The configuration options + * available via this API reflect the similarly-named elements of the + * {@code persistence.xml} file. + * + *

This API may not be used to configure a container-managed persistence + * unit. That is, the configured persistence unit should be considered a + * Java SE persistence unit, even when this API is used within the Jakarta + * EE environment. + * + *

If injection of the {@link EntityManagerFactory} is required, a CDI + * {@code Producer} may be used to make the {@link EntityManagerFactory} + * available as a CDI managed bean. + * + *

+ * @Produces @ApplicationScoped @Documents
+ * EntityManagerFactory configure() {
+ *     return new PersistenceConfiguration()
+ *             .name("DocumentData")
+ *             .nonJtaDataSource(datasource)
+ *             .managedClass(Document.class)
+ *             .createEntityManagerFactory();
+ * }
+ * 
+ * + *

Similarly, if injection of an {@link EntityManager} is required, + * a CDI {@code Producer} method/{@code Disposer} method pair may be + * used to make the {@link EntityManager} available as a CDI managed + * bean. + * + *

+ * @Produces @TransactionScoped @Documents
+ * EntityManager create(@Documents EntityManagerFactory factory) {
+ *     return factory.createEntityManager();
+ * }
+ *
+ * void close(@Disposes @Documents EntityManager entityManager) {
+ *     entityManager.close();
+ * }
+ * 
+ * + * @see Persistence#createEntityManagerFactory(PersistenceConfiguration) + * + * @since 3.2 + */ +public class PersistenceConfiguration { + + private String name; + private String provider; + private DataSource jtaDataSource; + private DataSource nonJtaDataSource; +// private URL persistenceUnitRootUrl; + + private SharedCacheMode sharedCacheMode = SharedCacheMode.UNSPECIFIED; + private ValidationMode validationMode = ValidationMode.AUTO; + private TransactionType transactionType = TransactionType.RESOURCE_LOCAL; +// private boolean excludeUnlistedClasses = false; + + private List jarFileUrls = new ArrayList<>(); + private List> managedClasses = new ArrayList<>(); + private List mappingFileNames = new ArrayList<>(); + private Map properties = new HashMap<>(); + + public enum TransactionType { JTA, RESOURCE_LOCAL } + + /** + * Create a new {@link EntityManagerFactory} based on this configuration. + * @throws IllegalStateException if required configuration is missing + */ + public EntityManagerFactory createEntityManagerFactory() { + return Persistence.createEntityManagerFactory(this); + } + + /** + * Specify the name of the persistence unit. + */ + public PersistenceConfiguration name(String name) { + this.name = name; + return this; + } + + /** + * @return the name of the persistence unit. + */ + public String name() { + return name; + } + +// /** +// * Specify a root URL for the persistence unit. +// * @param url the URL of a directory or JAR archive +// * @return this configuration +// */ +// public PersistenceConfiguration persistenceUnitRootUrl(URL url) { +// persistenceUnitRootUrl = url; +// return this; +// } +// +// /** +// * @return the root URL for the persistence unit, if any +// */ +// public URL persistenceUnitRootUrl() { +// return persistenceUnitRootUrl; +// } + + /** + * Specify the persistence provider. + * @param providerClassName the qualified name of the persistence provider class + * @return this configuration + */ + public PersistenceConfiguration provider(String providerClassName) { + this.provider = providerClassName; + return this; + } + + /** + * @return the qualified name of the persistence provider class. + */ + public String provider() { + return provider; + } + + /** + * Specify a JTA {@link DataSource}. + * @param dataSource the JTA datasource + * @return this configuration + */ + public PersistenceConfiguration jtaDataSource(DataSource dataSource) { + this.jtaDataSource = dataSource; + return this; + } + + /** + * @return the configured JTA datasource, if any + */ + public DataSource jtaDataSource() { + return jtaDataSource; + } + + /** + * Specify a non-JTA {@link DataSource}. + * @param dataSource the non-JTA datasource + * @return this configuration + */ + public PersistenceConfiguration nonJtaDataSource(DataSource dataSource) { + this.nonJtaDataSource = dataSource; + return this; + } + + /** + * @return the configured non-JTA datasource, if any + */ + public DataSource nonJtaDataSource() { + return nonJtaDataSource; + } + + /** + * Add a managed class (an {@link Entity}, {@link Embeddable}, or + * {@link MappedSuperclass}) to the configuration. + * @param managedClass the managed class + * @return this configuration + */ + public PersistenceConfiguration managedClass(Class managedClass) { + managedClasses.add(managedClass); + return this; + } + + /** + * @return all configured managed classes + */ + public List> managedClasses() { + return managedClasses; + } + + /** + * Add an {@code orm.xml} mapping file name to the configuration. + * @param name the file path of the mapping file + * @return this configuration + */ + public PersistenceConfiguration mappingFile(String name) { + mappingFileNames.add(name); + return this; + } + + /** + * @return all configured mapping file names + */ + public List mappingFiles() { + return mappingFileNames; + } + + /** + * Add a JAR archive to the configuration. + * @param url the URL of the JAR archive + * @return this configuration + */ + public PersistenceConfiguration jarFileUrl(URL url) { + jarFileUrls.add(url); + return this; + } + + /** + * @return all configured JAR archives + */ + public List jarFileUrls() { + return jarFileUrls; + } + + /** + * Specify the transaction type for the persistence unit. + * @param transactionType the transaction type + * @return this configuration + */ + public PersistenceConfiguration transactionType(TransactionType transactionType) { + this.transactionType = transactionType; + return this; + } + + /** + * @return the transaction type + */ + public TransactionType transactionType() { + return transactionType; + } + + /** + * Specify the shared cache mode for the persistence unit. + * @param sharedCacheMode the shared cache mode + * @return this configuration + */ + public PersistenceConfiguration sharedCacheMode(SharedCacheMode sharedCacheMode) { + this.sharedCacheMode = sharedCacheMode; + return this; + } + + /** + * @return the shared cache mode + */ + public SharedCacheMode sharedCacheMode() { + return sharedCacheMode; + } + + /** + * Specify the validation mode for the persistence unit. + * @param validationMode the shared cache mode + * @return this configuration + */ + public PersistenceConfiguration validationMode(ValidationMode validationMode) { + this.validationMode = validationMode; + return this; + } + + /** + * @return the validation mode + */ + public ValidationMode validationMode() { + return validationMode; + } + +// public PersistenceConfiguration excludeUnlistedClasses(boolean excludeUnlistedClasses) { +// this.excludeUnlistedClasses = excludeUnlistedClasses; +// return this; +// } +// +// public boolean excludeUnlistedClasses() { +// return excludeUnlistedClasses; +// } + + /** + * Set a property of this persistence unit. + * @param name the property name + * @param value the property value + * @return this configuration + */ + public PersistenceConfiguration property(String name, Object value) { + properties.put(name, value); + return this; + } + + /** + * Set multiple properties of this persistence unit. + * @param properties the properties + * @return this configuration + */ + public PersistenceConfiguration properties(Map properties) { + this.properties.putAll(properties); + return this; + } + + /** + * @return the configured properties + */ + public Map properties() { + return properties; + } +} diff --git a/api/src/main/java/jakarta/persistence/spi/PersistenceProvider.java b/api/src/main/java/jakarta/persistence/spi/PersistenceProvider.java index ed58c25d..5c31da99 100644 --- a/api/src/main/java/jakarta/persistence/spi/PersistenceProvider.java +++ b/api/src/main/java/jakarta/persistence/spi/PersistenceProvider.java @@ -18,6 +18,7 @@ import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; +import jakarta.persistence.PersistenceConfiguration; import jakarta.persistence.PersistenceException; import java.util.Map; @@ -45,10 +46,27 @@ public interface PersistenceProvider { * properties not specified in the persistence.xml * (and may be null if no properties are specified). * @return EntityManagerFactory for the persistence unit, - * or null if the provider is not the right provider + * or null if the provider is not the right provider + * + * @see Persistence#createEntityManagerFactory(String, Map) */ public EntityManagerFactory createEntityManagerFactory(String emName, Map map); + /** + * Called by Persistence class when an + * EntityManagerFactory is to be created. + * + * @param configuration the configuration of the persistence unit + * @return EntityManagerFactory for the persistence unit, + * or null if the provider is not the right provider + * @throws IllegalStateException if required configuration is missing + * + * @see Persistence#createEntityManagerFactory(PersistenceConfiguration) + * + * @since 3.2 + */ + public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration configuration); + /** * Called by the container when an EntityManagerFactory * is to be created.