
org.springframework.util.FlywayUtils Maven / Gradle / Ivy
package org.springframework.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.ReplacementTable;
import org.dbunit.dataset.datatype.IDataTypeFactory;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.ext.mssql.InsertIdentityOperation;
import org.dbunit.operation.DatabaseOperation;
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.vendor.Database;
public class FlywayUtils {
private final static Log logger = LogFactory.getLog(FlywayUtils.class);
/**
*
Class> clazz = getClass();
Class> databaseDialectClass = getDatabaseDialectClass(new JpaProperties().determineDatabase(jdbcTemplate.getDataSource()));
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*")));
final MetadataSources metadataSources = new MetadataSources();
for (BeanDefinition beanDefinition : provider.findCandidateComponents(ClassUtils.getPackageName(clazz))) {
metadataSources.addAnnotatedClassName(beanDefinition.getBeanClassName());
}
String[] packageNames = clazz.getPackage().getName().split("[.]");
if (packageNames != null && packageNames.length > 1) {
provider.setResourcePattern("*" + ClassUtils.CLASS_FILE_SUFFIX);
for (BeanDefinition beanDefinition : provider.findCandidateComponents(StringUtils.arrayToDelimitedString(Arrays.copyOf(packageNames, packageNames.length - 1), "."))) {
metadataSources.addAnnotatedClassName(beanDefinition.getBeanClassName());
}
}
final SchemaExport schemaExport = new SchemaExport();
schemaExport.setDelimiter(";");
schemaExport.setFormat(true);
final EnumSet targetTypes = EnumSet.of(TargetType.STDOUT, TargetType.SCRIPT);
try {
String prefix = ClassUtils.getShortName(clazz) + '_' + ClassUtils.getShortName(databaseDialectClass) + '_';
String suffix = ".sql";
File directory = Paths.get(SystemPropertyUtils.resolvePlaceholders("${user.home}"), Paths.get(SystemPropertyUtils.resolvePlaceholders("${java.io.tmpdir}")).toFile().getName()).toFile();
Assert.isTrue(directory != null && (directory.mkdirs() || directory.isDirectory()), "Create Directory fail... " + directory);
schemaExport.setOutputFile(File.createTempFile(prefix, suffix, directory).getPath());
}
catch (IOException e) {
throw new IllegalStateException(e);
}
final StandardServiceRegistryBuilder standardServiceRegistryBuilder = new StandardServiceRegistryBuilder(new BootstrapServiceRegistryBuilder().build());
standardServiceRegistryBuilder.applySettings(org.hibernate.cfg.Environment.getProperties());
standardServiceRegistryBuilder.applySetting(org.hibernate.cfg.AvailableSettings.DIALECT, databaseDialectClass);
jdbcTemplate.execute(new ConnectionCallback() {
@Override
public Void doInConnection(Connection connection) throws SQLException, DataAccessException {
standardServiceRegistryBuilder.applySetting(org.hibernate.cfg.AvailableSettings.HBM2DDL_CONNECTION, connection);
schemaExport.createOnly(targetTypes, metadataSources.getMetadataBuilder(standardServiceRegistryBuilder.build()).build());
return null;
}
});
private Class extends org.hibernate.dialect.Dialect> getDatabaseDialectClass(Database database) {
Assert.notNull(database, "'database' must not be null");
switch (database) {
case H2:
return H2Dialect.class;
case MYSQL:
return org.hibernate.dialect.MySQL5InnoDBDialect.class;
case SQL_SERVER:
return org.hibernate.dialect.SQLServer2008DialectCustom.class;
default:
throw new UnsupportedOperationException();
}
}
*
* @see javax.persistence.Persistence#generateSchema(String, java.util.Map)
*/
public static void DDL(ApplicationContext applicationContext, JdbcTemplate jdbcTemplate, Class> clazz) throws IOException {
Assert.notNull(applicationContext, "'applicationContext' must not be null");
JpaProperties jpaProperties = applicationContext.getBean(JpaProperties.class);
jpaProperties.getProperties().put("javax.persistence.schema-generation.database.action", "create");
jpaProperties.getProperties().put("javax.persistence.schema-generation.scripts.action", "create");
String id = applicationContext.getId();
if (StringUtils.hasText(id)) {
Database database = new JpaProperties().determineDatabase(jdbcTemplate.getDataSource());
File tmpdir = new File(SystemPropertyUtils.resolvePlaceholders("${java.io.tmpdir}"));
File directory = new File(SystemPropertyUtils.resolvePlaceholders("${user.home}"), StringUtils.getFilename(tmpdir.getName()));
Assert.isTrue(directory != null && (directory.mkdirs() || directory.isDirectory()), "Create Directory fail..." + directory);
jpaProperties.getProperties().put("javax.persistence.schema-generation.scripts.create-target",
File.createTempFile(ClassUtils.getShortName(clazz) + '_' + id.replace(':', '_') + '_' + database + '_', ".sql", directory).getCanonicalPath());
}
applicationContext.getBean(JpaBaseConfiguration.class).entityManagerFactory(null);
}
public static void DML(ApplicationContext applicationContext, JdbcTemplate jdbcTemplate, Class> clazz) {
Assert.notNull(applicationContext, "'applicationContext' must not be null");
Set resources = new LinkedHashSet();
resources.add(new ClassPathResource(ClassUtils.convertClassNameToResourcePath(ClassUtils.getPackageName(clazz)) + '/' + ClassUtils.getShortName(clazz) + ".xml"));
for (String profile : applicationContext.getEnvironment().getDefaultProfiles()) {
resources.add(new ClassPathResource(ClassUtils.convertClassNameToResourcePath(ClassUtils.getPackageName(clazz)) + '/' + ClassUtils.getShortName(clazz) + '_' + profile + ".xml"));
}
for (String profile : applicationContext.getEnvironment().getActiveProfiles()) {
resources.add(new ClassPathResource(ClassUtils.convertClassNameToResourcePath(ClassUtils.getPackageName(clazz)) + '/' + ClassUtils.getShortName(clazz) + '_' + profile + ".xml"));
}
Database database = new JpaProperties().determineDatabase(jdbcTemplate.getDataSource());
String lob = UUID.randomUUID().toString();
logger.info(String.format("%n%nUsing default lob: %s%n", lob));
for (Resource resource : resources) {
if (resource.exists()) {
String[] tableNames = jdbcTemplate.execute(new ConnectionCallback() {
/**
* @see java.nio.charset.StandardCharsets#UTF_8
* @see org.dbunit.dataset.xml.XmlDataSet#XmlDataSet(InputStream)
* @see org.dbunit.database.DatabaseConfig#FEATURE_CASE_SENSITIVE_TABLE_NAMES
*/
@Override
public String[] doInConnection(Connection con) throws SQLException, DataAccessException {
try (InputStream inputStream = resource.getInputStream(); AutoCloseableDatabaseConnection databaseConnection = new AutoCloseableDatabaseConnection(con)) {
databaseConnection.getConfig().setProperty(org.dbunit.database.DatabaseConfig.PROPERTY_DATATYPE_FACTORY, getDatatypeFactory(database));
databaseConnection.getConfig().setProperty(org.dbunit.database.DatabaseConfig.PROPERTY_ESCAPE_PATTERN, getEscapePattern(database));
databaseConnection.getConfig().setProperty(org.dbunit.database.DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, true);
FlatXmlDataSetBuilder flatXmlDataSetBuilder = new FlatXmlDataSetBuilder();
flatXmlDataSetBuilder.setColumnSensing(true);
flatXmlDataSetBuilder.setCaseSensitiveTableNames(true);
ReplacementDataSet replacementDataSet = new ReplacementDataSet(flatXmlDataSetBuilder.build(inputStream));
replacementDataSet.addReplacementObject(ReplacementTable.NO_VALUE, null);
replacementDataSet.addReplacementObject("[null]", null);
replacementDataSet.addReplacementObject("[date]", new Date());
replacementDataSet.addReplacementObject("[lob]", lob.getBytes());
DatabaseOperation databaseOperation = DatabaseOperation.INSERT;
if (database != null && database == Database.SQL_SERVER) {
databaseOperation = new InsertIdentityOperation(databaseOperation);
}
databaseOperation.execute(databaseConnection, replacementDataSet);
return replacementDataSet.getTableNames();
}
catch (SQLException | IOException | DatabaseUnitException e) {
throw new SQLException("DBunit execute fail... from " + resource, e);
}
}
});
logger.info("Table: " + Arrays.asList(tableNames));
}
}
}
// "'?'"
private static String getEscapePattern(Database database) {
Assert.notNull(database, "'database' must not be null");
switch (database) {
case H2:
return "\"?\"";
case MYSQL:
return "`?`";
case SQL_SERVER:
return "[?]";
default:
return "?";
}
}
/**
* @see UnsupportedOperationException
*/
private static IDataTypeFactory getDatatypeFactory(Database database) {
Assert.notNull(database, "'database' must not be null");
switch (database) {
case H2:
return new org.dbunit.ext.h2.H2DataTypeFactory();
case MYSQL:
return new org.dbunit.ext.mysql.MySqlDataTypeFactory();
case SQL_SERVER:
return new org.dbunit.ext.mssql.MsSqlDataTypeFactory();
default:
return new org.dbunit.dataset.datatype.DefaultDataTypeFactory();
}
}
}
class AutoCloseableDatabaseConnection extends DatabaseConnection implements AutoCloseable {
public AutoCloseableDatabaseConnection(Connection connection) throws DatabaseUnitException {
super(connection);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy