Generating SQL files in springBoot – SchemaExport implementation 01 in Hibernate5 (hibernate5.0.x)
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
MetadataImplementor metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ).buildMetadata();
SchemaExport schemaExport = new SchemaExport(metadata);
schemaExport.create(true, true);
Copy the code
Let’s take a look at generating SQL during boot in springBoot. There are two ways to achieve this: the first is the initial version, and the second is a simplified version of the first. The two packages can be used as appropriate.
).
In the first release, the Hibernate Config configuration was obtained by manually injecting the key BEEN. Divided into two files HibernateJavaConfig. Java and GenerateDDLApplicationRunner. Java
HibernateJavaConfig.java
This file is used to implement Hibernate configuration, similar to hibernate.cfg.xml. The following objects are obtained manually by explicitly creating been:
org.hibernate.boot.Metadata
org.hibernate.boot.registry.StandardServiceRegistry
javax.persistence.spi.PersistenceUnitInfo
The full file is as follows:
package com.windcoder.qycms.core.basis.test.Hibernate.ddl; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.domain.EntityScanPackages; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager; import javax.persistence.spi.PersistenceUnitInfo; import java.util.List; import java.util.Map; @Configuration @EntityScan("com.windcoder.qycms.*") @AutoConfigureAfter({HibernateJpaAutoConfiguration.class}) public Class HibernateJavaConfig {/** * Generate Metadata * where the class to be parsed is added to the Metadata * @param standardServiceRegistry * @param persistenceUnitInfo * @return */ @ConditionalOnMissingBean({Metadata.class}) @Bean public Metadata getMetadata(StandardServiceRegistry standardServiceRegistry, PersistenceUnitInfo persistenceUnitInfo) { MetadataSources metadataSources = new MetadataSources(standardServiceRegistry); List<String> managedClassNames = persistenceUnitInfo.getManagedClassNames(); for (String managedClassName : managedClassNames) { metadataSources.addAnnotatedClassName(managedClassName); } Metadata metadata = metadataSources.buildMetadata(); return metadata; } / * * * the instance will merge configuration information to a group of working service * @ param jpaProperties * @ return * / @ ConditionalOnMissingBean ({StandardServiceRegistry. Class}) @Bean public StandardServiceRegistry getStandardServiceRegistry(JpaProperties jpaProperties) { StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder(); Map<String, String> properties = jpaProperties.getProperties(); ssrb.applySettings(properties); StandardServiceRegistry ssr = ssrb.build(); return ssr; } / * * * PersistenceUnitInfo interface implemented by container and by creating a javax.mail. Persistence. When the EntityManagerFactory persistence provider is used, * The Been that is used to generate PersistenceUnitInfo instead of persistence.xml * @param entityScanPackages * @return */ @ConditionalOnMissingBean({PersistenceUnitInfo.class}) @Bean public PersistenceUnitInfo getPersistenceUnitInfo(EntityScanPackages entityScanPackages) { List<String> packagesToScan = entityScanPackages.getPackageNames(); DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager(); String[] packagesToScanArr = (String[]) packagesToScan.toArray(new String[packagesToScan.size()]); persistenceUnitManager.setPackagesToScan(packagesToScanArr); persistenceUnitManager.afterPropertiesSet(); PersistenceUnitInfo persistenceUnitInfo = persistenceUnitManager.obtainDefaultPersistenceUnitInfo(); return persistenceUnitInfo; }}Copy the code
Here we need @Entityscan (“com.windcoder.qycms.*”) to set the scan scope so that entityScanPackages can automatically generate the default been.
GenerateDDLApplicationRunner.java
package com.windcoder.qycms.core.basis.test.Hibernate.ddl; import org.hibernate.boot.Metadata; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import java.io.File; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Calendar; /** * The last class to generate SQL * http://docs.jboss.org/hibernate/orm/5.0/quickstart/html/ * / @ Component public class GenerateDDLApplicationRunner implements ApplicationRunner { private Metadata metadata; private static final String SCHEMA_SQL2 = "db/base/update-2-ddl_%s.sql"; public GenerateDDLApplicationRunner(Metadata metadata) { this.metadata = metadata; } /** * */ public void run(ApplicationArguments args) throws Exception { File dropAndCreateDdlFile = new File(getOutputFilename()); deleteFileIfExists(dropAndCreateDdlFile); SchemaExport schemaExport = new SchemaExport((MetadataImplementor) metadata); schemaExport.setDelimiter(";" ); schemaExport.setFormat(false); schemaExport.setOutputFile(dropAndCreateDdlFile.getAbsolutePath()); schemaExport.execute(true, false, false, false); } /** * Check the output path of the file to be generated, If there is the delete * / private void deleteFileIfExists (File dropAndCreateDdlFile) {if (dropAndCreateDdlFile. The exists ()) {if (! dropAndCreateDdlFile.isFile()) { String msg = MessageFormat.format("File is not a normal file {0}", dropAndCreateDdlFile); throw new IllegalStateException(msg); } if (! dropAndCreateDdlFile.delete()) { String msg = MessageFormat.format("Unable to delete file {0}", dropAndCreateDdlFile); throw new IllegalStateException(msg); /** * Format output path */ private static String getOutputFilename() {SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMdd_HHmmss"); String currentDate = sdf.format(Calendar.getInstance().getTime()); return String.format(SCHEMA_SQL2, currentDate); }}Copy the code
Change numerous for brief
Through the configuration and implementation of the above two files, the implementation principle is almost understood, now start to simplify, the whole file:
package com.windcoder.qycms.core.basis.test.Hibernate.ddl;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
@Component
public class JPASchemaExtractor2 implements ApplicationRunner {
private static final String SCHEMA_SQL2 = "db/base/create-ddl_2_%s.sql";
@Autowired
LocalContainerEntityManagerFactoryBean fb;
@Override
public void run(ApplicationArguments args) throws Exception {
StandardServiceRegistry standardServiceRegistry = new StandardServiceRegistryBuilder()
.applySettings(fb.getJpaPropertyMap())
.build();
MetadataSources metadata = new MetadataSources(standardServiceRegistry);
List<String> managedClassNames = fb.getPersistenceUnitInfo().getManagedClassNames();
for (String managedClassName : managedClassNames) {
metadata.addAnnotatedClassName(managedClassName);
}
MetadataImplementor metadataImplementor = (MetadataImplementor) metadata.getMetadataBuilder().build();
SchemaExport schemaExport = new SchemaExport(metadataImplementor);
String outputFile = getOutputFilename();
schemaExport.setOutputFile(outputFile);
schemaExport.setDelimiter(";");
schemaExport.setFormat(false);
schemaExport.execute(true, false, false, false);
}
private static String getOutputFilename() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
String currentDate = sdf.format(Calendar.getInstance().getTime());
return String.format(SCHEMA_SQL2, currentDate);
}
}
Copy the code
By contrast, whether LocalContainerEntityManagerFactoryBean replaces the previous explicit code implementation.
According to the official definition:
This FactoryBean creates the JPA EntityManagerFactory according to JPA’s standard container bootstrap convention.
This is the most powerful way to set up a shared JPA EntityManagerFactory in the context of a Spring application; The EntityManagerFactory can then be passed to the JPA-based DAO through dependency injection.
Note: can be configured to switch to JNDI lookup or switch to LocalEntityManagerFactoryBean definition.
Like LocalEntityManagerFactoryBean, configuration Settings are usually based on conventional JPA configuration agreement from reside in the classpath meta-inf/persistence reads the XML configuration file.
However, this FactoryBean is more flexible in that you can override the location of the persistence. XML file, specify the JDBC DataSources to link to, and so on. In addition, it allows pluggable class detection through Spring’s LoadTimeWeaver abstraction, rather than binding to a special VM agent specified at JVM startup.
Internally, this FactoryBean parses the persistence. XML file itself and creates the PersistenceUnitInfo object (which contains other configurations, such as JDBC DataSources and Spring LoadTimeWeaver), To be passed to the selected JPA PersistenceProvider. This is a native JPA container that fully supports standard JPA container conventions.
The exposed EntityManagerFactory object implements the following two interfaces: the underlying native EntityManagerFactory interface returned by the -PersistenceProvider; – EntityManagerFactoryInfo interface for other metadata assembled by this FactoryBean;
Class LocalContainerEntityManagerFactoryBean