blob: 03b55835f1c3489878255ce91732edfa9f0981b8 [file] [log] [blame]
package org.apache.airavata.common.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import javax.persistence.Cache;
// import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceUnitUtil;
// import javax.persistence.Query;
// import javax.persistence.SynchronizationType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.metamodel.Metamodel;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.meta.MappingTool;
import org.apache.openjpa.lib.util.Options;
import org.apache.openjpa.persistence.ArgumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JPAUtils
*/
public class JPAUtils {
private static class EntityManagerFactoryWrapper implements EntityManagerFactory {
private final EntityManagerFactory factory;
private final JDBCConfig jdbcConfig;
EntityManagerFactoryWrapper(EntityManagerFactory factory, JDBCConfig jdbcConfig) {
this.factory = factory;
this.jdbcConfig = jdbcConfig;
}
@Override
public EntityManager createEntityManager() {
return wrapCreateEntityManager(() -> this.factory.createEntityManager());
}
@Override
public EntityManager createEntityManager(Map map) {
return wrapCreateEntityManager(() -> this.factory.createEntityManager(map));
}
// @Override
// public EntityManager createEntityManager(SynchronizationType synchronizationType) {
// return wrapCreateEntityManager(() -> this.factory.createEntityManager(synchronizationType));
// }
// @Override
// public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
// return wrapCreateEntityManager(() -> this.factory.createEntityManager(synchronizationType, map));
// }
private EntityManager wrapCreateEntityManager(Supplier<EntityManager> entityManagerSupplier) {
try {
return entityManagerSupplier.get();
} catch (ArgumentException e) {
Map<String, String> finalProperties = new HashMap<>(JPAUtils.DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES);
finalProperties.putAll(JPAUtils.createConnectionProperties(this.jdbcConfig));
JDBCConfiguration jdbcConfiguration = new JDBCConfigurationImpl();
jdbcConfiguration.fromProperties(finalProperties);
Options options = new Options();
options.put("sqlFile", "migration.sql");
// If you want to generate the entire schema instead of just what is
// needed to bring the database up to date, use schemaAction=build
// options.put("schemaAction", "build");
options.put("foreignKeys", "true");
options.put("indexes", "true");
options.put("primaryKeys", "true");
try {
MappingTool.run(jdbcConfiguration, new String[] {}, options, null);
} catch (Exception mappingToolEx) {
logger.error("Failed to run MappingTool", mappingToolEx);
throw new RuntimeException(
"Failed to get EntityManager, then failed to run MappingTool to generate migration script",
e);
}
throw new RuntimeException("Failed to get EntityManager, but successfully executed "
+ "MappingTool to generate migration script (to file named "
+ "migration.sql) in case the error was caused by the database "
+ "schema being out of date with the mappings", e);
}
}
@Override
public CriteriaBuilder getCriteriaBuilder() {
return this.factory.getCriteriaBuilder();
}
@Override
public Metamodel getMetamodel() {
return this.factory.getMetamodel();
}
@Override
public boolean isOpen() {
return this.factory.isOpen();
}
@Override
public void close() {
this.factory.close();
}
@Override
public Map<String, Object> getProperties() {
return this.factory.getProperties();
}
@Override
public Cache getCache() {
return this.factory.getCache();
}
@Override
public PersistenceUnitUtil getPersistenceUnitUtil() {
return this.factory.getPersistenceUnitUtil();
}
// @Override
// public void addNamedQuery(String name, Query query) {
// this.factory.addNamedQuery(name, query);
// }
// @Override
// public <T> T unwrap(Class<T> cls) {
// return this.factory.unwrap(cls);
// }
// @Override
// public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
// this.factory.addNamedEntityGraph(graphName, entityGraph);
// }
}
private final static Logger logger = LoggerFactory.getLogger(JPAUtils.class);
private final static Map<String, String> DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES;
static {
Map<String, String> properties = new HashMap<String, String>();
properties.put("openjpa.ConnectionDriverName", "org.apache.commons.dbcp.BasicDataSource");
properties.put("openjpa.DynamicEnhancementAgent", "true");
properties.put("openjpa.RuntimeUnenhancedClasses", "unsupported");
properties.put("openjpa.RemoteCommitProvider", "sjvm");
properties.put("openjpa.Log", "DefaultLevel=INFO, Runtime=INFO, Tool=INFO, SQL=INFO");
// use the following to enable logging of all SQL statements
// properties.put("openjpa.Log", "DefaultLevel=INFO, Runtime=INFO, Tool=INFO,
// SQL=TRACE");
properties.put("openjpa.jdbc.SynchronizeMappings", "validate");
properties.put("openjpa.jdbc.QuerySQLCache", "false");
properties.put("openjpa.DetachState", "all");
properties.put("openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=72,"
+ " PrintParameters=true, MaxActive=10, MaxIdle=5, MinIdle=2, MaxWait=31536000, autoReconnect=true");
DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES = properties;
}
/**
* Create an {@link EntityManagerFactory} with the default settings.
*
* @param persistenceUnitName
* @param jdbcConfig
* @return {@link EntityManagerFactory}
*/
public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, JDBCConfig jdbcConfig) {
return getEntityManagerFactory(persistenceUnitName, jdbcConfig, Collections.emptyMap());
}
/**
* Create an {@link EntityManagerFactory}. The given properties will override
* the default properties.
*
* @param persistenceUnitName
* @param jdbcConfig
* @param properties
* @return {@link EntityManagerFactory}
*/
public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, JDBCConfig jdbcConfig,
Map<String, String> properties) {
Map<String, String> finalProperties = new HashMap<>(DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES);
finalProperties.putAll(createConnectionProperties(jdbcConfig));
finalProperties.putAll(properties);
return new EntityManagerFactoryWrapper(
Persistence.createEntityManagerFactory(persistenceUnitName, finalProperties), jdbcConfig);
}
private static Map<String, String> createConnectionProperties(JDBCConfig jdbcConfig) {
String connectionProperties = "DriverClassName=" + jdbcConfig.getDriver() + "," + "Url=" + jdbcConfig.getURL()
+ "?autoReconnect=true," + "Username=" + jdbcConfig.getUser() + "," + "Password="
+ jdbcConfig.getPassword() + ",validationQuery=" + jdbcConfig.getValidationQuery();
logger.debug("Connection properties={}", connectionProperties);
return Collections.singletonMap("openjpa.ConnectionProperties", connectionProperties);
}
}