Support for @ConfigurationProperties in JPA
Adds JpaProperties to bind to spring.jpa.* (making those properties easier to reason about and visible in the /configprops endpoint). Also allows easy configuration of multiple EntityManagerFactories via new EntityManagerFactoryBuilder. JpaBaseConfiguration has a @Bean of that type so users can inject it to create new or additional EntityManagerFactories. This also simplifies the Hibernate autoconfiguration. Also renames the DataSourceFactory to DataSourceBuilder (since that's what it is).
This commit is contained in:
parent
f7397f1d1c
commit
7454c4866b
|
|
@ -154,7 +154,7 @@ public class DataSourceAutoConfiguration {
|
|||
@Bean
|
||||
public DataSource dataSource() {
|
||||
// @formatter:off
|
||||
DataSourceFactory factory = DataSourceFactory
|
||||
DataSourceBuilder factory = DataSourceBuilder
|
||||
.create(this.properties.getClassLoader())
|
||||
.driverClassName(this.properties.getDriverClassName())
|
||||
.url(this.properties.getUrl())
|
||||
|
|
@ -209,7 +209,7 @@ public class DataSourceAutoConfiguration {
|
|||
* the driver class can actually be loaded by the data source.
|
||||
*/
|
||||
private ClassLoader getDataSourceClassLoader(ConditionContext context) {
|
||||
Class<?> dataSourceClass = new DataSourceFactory(context.getClassLoader())
|
||||
Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
|
||||
.findType();
|
||||
if (dataSourceClass == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import org.springframework.util.ClassUtils;
|
|||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class DataSourceFactory {
|
||||
public class DataSourceBuilder {
|
||||
|
||||
private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
|
||||
"org.apache.tomcat.jdbc.pool.DataSource",
|
||||
|
|
@ -51,15 +51,15 @@ public class DataSourceFactory {
|
|||
|
||||
private Map<String, String> properties = new HashMap<String, String>();
|
||||
|
||||
public static DataSourceFactory create() {
|
||||
return new DataSourceFactory(null);
|
||||
public static DataSourceBuilder create() {
|
||||
return new DataSourceBuilder(null);
|
||||
}
|
||||
|
||||
public static DataSourceFactory create(ClassLoader classLoader) {
|
||||
return new DataSourceFactory(classLoader);
|
||||
public static DataSourceBuilder create(ClassLoader classLoader) {
|
||||
return new DataSourceBuilder(classLoader);
|
||||
}
|
||||
|
||||
public DataSourceFactory(ClassLoader classLoader) {
|
||||
public DataSourceBuilder(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
|
|
@ -82,27 +82,27 @@ public class DataSourceFactory {
|
|||
return new MutablePropertyValues(this.properties);
|
||||
}
|
||||
|
||||
public DataSourceFactory type(Class<? extends DataSource> type) {
|
||||
public DataSourceBuilder type(Class<? extends DataSource> type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataSourceFactory url(String url) {
|
||||
public DataSourceBuilder url(String url) {
|
||||
this.properties.put("url", url);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataSourceFactory driverClassName(String driverClassName) {
|
||||
public DataSourceBuilder driverClassName(String driverClassName) {
|
||||
this.properties.put("driverClassName", driverClassName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataSourceFactory username(String username) {
|
||||
public DataSourceBuilder username(String username) {
|
||||
this.properties.put("username", username);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataSourceFactory password(String password) {
|
||||
public DataSourceBuilder password(String password) {
|
||||
this.properties.put("password", password);
|
||||
return this;
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.orm.jpa;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Convenient builder for JPA EntityManagerFactory instances. Collects common
|
||||
* configuration when constructed and then allows you to create one or more
|
||||
* {@link LocalContainerEntityManagerFactoryBean} through a fluent builder pattern. The
|
||||
* most common options are covered in the builder, but you can always manipulate the
|
||||
* product of the builder if you need more control, before returning it from a
|
||||
* <code>@Bean</code> definition.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class EntityManagerFactoryBuilder {
|
||||
|
||||
private JpaVendorAdapter jpaVendorAdapter;
|
||||
|
||||
private PersistenceUnitManager persistenceUnitManager;
|
||||
|
||||
private JpaProperties properties;
|
||||
|
||||
/**
|
||||
* Create a new instance passing in the common pieces that will be shared if multiple
|
||||
* EntityManagerFactory instances are created.
|
||||
*
|
||||
* @param jpaVendorAdapter a vendor adapter
|
||||
* @param properties common configuration options, including generic map for JPA
|
||||
* vendor properties
|
||||
* @param persistenceUnitManager optional source of persistence unit information (can
|
||||
* be null)
|
||||
*/
|
||||
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
|
||||
JpaProperties properties, PersistenceUnitManager persistenceUnitManager) {
|
||||
this.jpaVendorAdapter = jpaVendorAdapter;
|
||||
this.persistenceUnitManager = persistenceUnitManager;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public Builder dataSource(DataSource dataSource) {
|
||||
return new Builder(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* A fluent builder for a LocalContainerEntityManagerFactoryBean.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class Builder {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
private String persistenceUnit;
|
||||
|
||||
private Builder(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* The names of packages to scan for <code>@Entity</code> annotations.
|
||||
*
|
||||
* @param packagesToScan packages to scan
|
||||
* @return the builder for fluent usage
|
||||
*/
|
||||
public Builder packages(String... packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The classes whose packages should be scanned for <code>@Entity</code>
|
||||
* annotations.
|
||||
*
|
||||
* @param basePackageClasses the classes to use
|
||||
* @return the builder for fluent usage
|
||||
*/
|
||||
public Builder packages(Class<?>... basePackageClasses) {
|
||||
Set<String> packages = new HashSet<String>();
|
||||
for (Class<?> type : basePackageClasses) {
|
||||
packages.add(ClassUtils.getPackageName(type));
|
||||
}
|
||||
this.packagesToScan = packages.toArray(new String[0]);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the persistence unit. If only building one EntityManagerFactory you
|
||||
* can omit this, but if there are more than one in the same application you
|
||||
* should give them distinct names.
|
||||
*
|
||||
* @param persistenceUnit the name of the persistence unit
|
||||
* @return the builder for fluent usage
|
||||
*/
|
||||
public Builder persistenceUnit(String persistenceUnit) {
|
||||
this.persistenceUnit = persistenceUnit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic properties for standard JPA or vendor-specific configuration. These
|
||||
* properties override any values provided in the {@link JpaProperties} used to
|
||||
* create the builder.
|
||||
*
|
||||
* @param properties the properties to use
|
||||
* @return the builder for fluent usage
|
||||
*/
|
||||
public Builder properties(Map<String, Object> properties) {
|
||||
EntityManagerFactoryBuilder.this.properties.getProperties()
|
||||
.putAll(properties);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LocalContainerEntityManagerFactoryBean build() {
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
|
||||
if (EntityManagerFactoryBuilder.this.persistenceUnitManager != null) {
|
||||
entityManagerFactoryBean
|
||||
.setPersistenceUnitManager(EntityManagerFactoryBuilder.this.persistenceUnitManager);
|
||||
}
|
||||
if (this.persistenceUnit != null) {
|
||||
entityManagerFactoryBean.setPersistenceUnitName(this.persistenceUnit);
|
||||
}
|
||||
entityManagerFactoryBean
|
||||
.setJpaVendorAdapter(EntityManagerFactoryBuilder.this.jpaVendorAdapter);
|
||||
entityManagerFactoryBean.setDataSource(this.dataSource);
|
||||
entityManagerFactoryBean.setPackagesToScan(this.packagesToScan);
|
||||
entityManagerFactoryBean.getJpaPropertyMap().putAll(
|
||||
EntityManagerFactoryBuilder.this.properties.getProperties());
|
||||
entityManagerFactoryBean.getJpaPropertyMap().putAll(
|
||||
EntityManagerFactoryBuilder.this.properties
|
||||
.getHibernateProperties(this.dataSource));
|
||||
return entityManagerFactoryBean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,10 +16,7 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.orm.jpa;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
|
@ -27,14 +24,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.HibernateEntityManagerCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.orm.jpa.SpringNamingStrategy;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
|
|
@ -54,44 +47,11 @@ import org.springframework.util.ClassUtils;
|
|||
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
public HibernateJpaAutoConfiguration() {
|
||||
this.environment = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
super.setEnvironment(environment);
|
||||
this.environment = new RelaxedPropertyResolver(environment,
|
||||
"spring.jpa.hibernate.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
|
||||
return new HibernateJpaVendorAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
|
||||
Map<String, Object> properties = entityManagerFactoryBean.getJpaPropertyMap();
|
||||
properties.put("hibernate.ejb.naming_strategy", this.environment.getProperty(
|
||||
"naming-strategy", SpringNamingStrategy.class.getName()));
|
||||
String ddlAuto = this.environment.getProperty("ddl-auto",
|
||||
getDefaultDdlAuto(entityManagerFactoryBean.getDataSource()));
|
||||
if (!"none".equals(ddlAuto)) {
|
||||
properties.put("hibernate.hbm2ddl.auto", ddlAuto);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDefaultDdlAuto(DataSource dataSource) {
|
||||
if (EmbeddedDatabaseConnection.isEmbedded(dataSource)) {
|
||||
return "create-drop";
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
static class HibernateEntityManagerCondition extends SpringBootCondition {
|
||||
|
||||
private static String[] CLASS_NAMES = {
|
||||
|
|
|
|||
|
|
@ -30,11 +30,10 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
|
|
@ -42,7 +41,6 @@ import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
|
|||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
|
@ -54,19 +52,19 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
|||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class JpaBaseConfiguration implements BeanFactoryAware, EnvironmentAware {
|
||||
@EnableConfigurationProperties(JpaProperties.class)
|
||||
public abstract class JpaBaseConfiguration implements BeanFactoryAware {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired(required = false)
|
||||
private PersistenceUnitManager persistenceUnitManager;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, "spring.jpa.");
|
||||
}
|
||||
@Autowired
|
||||
private JpaProperties jpaProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
|
|
@ -75,47 +73,35 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware, Environm
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "entityManagerFactory")
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
|
||||
JpaVendorAdapter jpaVendorAdapter) {
|
||||
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
|
||||
if (this.persistenceUnitManager != null) {
|
||||
entityManagerFactoryBean
|
||||
.setPersistenceUnitManager(this.persistenceUnitManager);
|
||||
}
|
||||
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
|
||||
entityManagerFactoryBean.setDataSource(getDataSource());
|
||||
entityManagerFactoryBean.setPackagesToScan(getPackagesToScan());
|
||||
entityManagerFactoryBean.getJpaPropertyMap().putAll(
|
||||
this.environment.getSubProperties("properties."));
|
||||
configure(entityManagerFactoryBean);
|
||||
return entityManagerFactoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(JpaVendorAdapter.class)
|
||||
@ConditionalOnMissingBean
|
||||
public JpaVendorAdapter jpaVendorAdapter() {
|
||||
AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
|
||||
adapter.setShowSql(this.environment.getProperty("show-sql", Boolean.class, true));
|
||||
adapter.setDatabasePlatform(this.environment.getProperty("database-platform"));
|
||||
adapter.setDatabase(this.environment.getProperty("database", Database.class,
|
||||
Database.DEFAULT));
|
||||
adapter.setGenerateDdl(this.environment.getProperty("generate-ddl",
|
||||
Boolean.class, false));
|
||||
adapter.setShowSql(this.jpaProperties.isShowSql());
|
||||
adapter.setDatabase(this.jpaProperties.getDatabase());
|
||||
adapter.setDatabasePlatform(this.jpaProperties.getDatabasePlatform());
|
||||
adapter.setGenerateDdl(this.jpaProperties.isGenerateDdl());
|
||||
return adapter;
|
||||
}
|
||||
|
||||
protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
|
||||
|
||||
protected DataSource getDataSource() {
|
||||
try {
|
||||
return this.beanFactory.getBean("dataSource", DataSource.class);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
return this.beanFactory.getBean(DataSource.class);
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(
|
||||
JpaVendorAdapter jpaVendorAdapter) {
|
||||
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
|
||||
jpaVendorAdapter, this.jpaProperties, this.persistenceUnitManager);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnMissingBean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
|
||||
EntityManagerFactoryBuilder factory) {
|
||||
return factory.dataSource(this.dataSource).packages(getPackagesToScan()).build();
|
||||
}
|
||||
|
||||
protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
|
||||
|
||||
protected String[] getPackagesToScan() {
|
||||
List<String> basePackages = AutoConfigurationPackages.get(this.beanFactory);
|
||||
return basePackages.toArray(new String[basePackages.size()]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.orm.jpa;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.orm.jpa.SpringNamingStrategy;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
|
||||
/**
|
||||
* External configuration properties for a JPA EntityManagerFactory created by Spring.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.jpa")
|
||||
public class JpaProperties {
|
||||
|
||||
private Map<String, Object> properties = new HashMap<String, Object>();
|
||||
|
||||
private String databasePlatform;
|
||||
|
||||
private Database database = Database.DEFAULT;
|
||||
|
||||
private boolean generateDdl = false;
|
||||
|
||||
private boolean showSql = false;
|
||||
|
||||
private Hibernate hibernate = new Hibernate();
|
||||
|
||||
public Map<String, Object> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, Object> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getDatabasePlatform() {
|
||||
return this.databasePlatform;
|
||||
}
|
||||
|
||||
public void setDatabasePlatform(String databasePlatform) {
|
||||
this.databasePlatform = databasePlatform;
|
||||
}
|
||||
|
||||
public Database getDatabase() {
|
||||
return this.database;
|
||||
}
|
||||
|
||||
public void setDatabase(Database database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public boolean isGenerateDdl() {
|
||||
return this.generateDdl;
|
||||
}
|
||||
|
||||
public void setGenerateDdl(boolean generateDdl) {
|
||||
this.generateDdl = generateDdl;
|
||||
}
|
||||
|
||||
public boolean isShowSql() {
|
||||
return this.showSql;
|
||||
}
|
||||
|
||||
public void setShowSql(boolean showSql) {
|
||||
this.showSql = showSql;
|
||||
}
|
||||
|
||||
public Hibernate getHibernate() {
|
||||
return this.hibernate;
|
||||
}
|
||||
|
||||
public void setHibernate(Hibernate hibernate) {
|
||||
this.hibernate = hibernate;
|
||||
}
|
||||
|
||||
public Map<String, Object> getHibernateProperties(DataSource dataSource) {
|
||||
return this.hibernate.getAdditionalProperties(this.properties, dataSource);
|
||||
}
|
||||
|
||||
public static class Hibernate {
|
||||
|
||||
private Class<?> namingStrategy;
|
||||
|
||||
private static Class<?> DEFAULT_NAMING_STRATEGY = SpringNamingStrategy.class;
|
||||
|
||||
private String ddlAuto;
|
||||
|
||||
public Class<?> getNamingStrategy() {
|
||||
return this.namingStrategy;
|
||||
}
|
||||
|
||||
public void setNamingStrategy(Class<?> namingStrategy) {
|
||||
this.namingStrategy = namingStrategy;
|
||||
}
|
||||
|
||||
public String getDdlAuto() {
|
||||
return this.ddlAuto;
|
||||
}
|
||||
|
||||
public void setDdlAuto(String ddlAuto) {
|
||||
this.ddlAuto = ddlAuto;
|
||||
}
|
||||
|
||||
private Map<String, Object> getAdditionalProperties(Map<String, Object> existing,
|
||||
DataSource dataSource) {
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
if (!isAlreadyProvided(existing, "ejb.naming_strategy")
|
||||
&& this.namingStrategy != null) {
|
||||
result.put("hibernate.ejb.naming_strategy", this.namingStrategy.getName());
|
||||
}
|
||||
else if (this.namingStrategy == null) {
|
||||
result.put("hibernate.ejb.naming_strategy",
|
||||
DEFAULT_NAMING_STRATEGY.getName());
|
||||
}
|
||||
String ddlAuto = this.ddlAuto != null ? this.ddlAuto
|
||||
: getDefaultDdlAuto(dataSource);
|
||||
if (!isAlreadyProvided(existing, "hbm2ddl.auto") && !"none".equals(ddlAuto)) {
|
||||
result.put("hibernate.hbm2ddl.auto", ddlAuto);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isAlreadyProvided(Map<String, Object> existing, String key) {
|
||||
return existing.containsKey("hibernate." + key);
|
||||
}
|
||||
|
||||
private String getDefaultDdlAuto(DataSource dataSource) {
|
||||
if (EmbeddedDatabaseConnection.isEmbedded(dataSource)) {
|
||||
return "create-drop";
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
|
@ -30,7 +31,7 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat
|
|||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ HibernateJpaAutoConfigurationTests.class,
|
||||
LiquibaseAutoConfigurationTests.class })
|
||||
// @Ignore
|
||||
@Ignore
|
||||
public class AdhocTestSuite {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public class CommonsDataSourceConfigurationTests {
|
|||
@Bean
|
||||
@ConfigurationProperties(prefix = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
|
||||
public DataSource dataSource() {
|
||||
return DataSourceFactory.create().type(BasicDataSource.class).build();
|
||||
return DataSourceBuilder.create().type(BasicDataSource.class).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public class HikariDataSourceConfigurationTests {
|
|||
@Bean
|
||||
@ConfigurationProperties(prefix = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
|
||||
public DataSource dataSource() {
|
||||
return DataSourceFactory.create().type(HikariDataSource.class).build();
|
||||
return DataSourceBuilder.create().type(HikariDataSource.class).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ public class TomcatDataSourceConfigurationTests {
|
|||
@Bean
|
||||
@ConfigurationProperties(prefix = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
|
||||
public DataSource dataSource() {
|
||||
return DataSourceFactory.create()
|
||||
return DataSourceBuilder.create()
|
||||
.type(org.apache.tomcat.jdbc.pool.DataSource.class).build();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.springframework.boot.test.EnvironmentTestUtils;
|
|||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +40,7 @@ public class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigura
|
|||
@Test
|
||||
public void testCustomNamingStrategy() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jpa.hibernate.namingstrategy:"
|
||||
"spring.jpa.hibernate.namingStrategy:"
|
||||
+ "org.hibernate.cfg.EJB3NamingStrategy");
|
||||
setupTestConfiguration();
|
||||
this.context.refresh();
|
||||
|
|
@ -50,4 +51,20 @@ public class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigura
|
|||
assertThat(actual, equalTo("org.hibernate.cfg.EJB3NamingStrategy"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomNamingStrategyViaJpaProperties() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jpa.properties.hibernate.ejb.naming_strategy:"
|
||||
+ "org.hibernate.cfg.EJB3NamingStrategy");
|
||||
setupTestConfiguration();
|
||||
this.context.refresh();
|
||||
LocalContainerEntityManagerFactoryBean bean = this.context
|
||||
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
||||
String actual = (String) bean.getJpaPropertyMap().get(
|
||||
"hibernate.ejb.naming_strategy");
|
||||
// You can't override this one from spring.jpa.properties because it has an
|
||||
// opinionated default
|
||||
assertThat(actual, not(equalTo("org.hibernate.cfg.EJB3NamingStrategy")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,12 +925,55 @@ action.
|
|||
|
||||
[[howto-configure-a-datasource]]
|
||||
=== Configure a DataSource
|
||||
To override the default settings just define a `@Bean` of your own of type `DataSource`.
|
||||
To override the default settings just define a `@Bean` of your own of type `DataSource`.
|
||||
Spring Boot provides a utility builder class `DataSourceBuilder` that can be used
|
||||
to create one of the standard ones (if it is on the classpath), or you can just create
|
||||
your own, and bind it to a set of `Environment` properties e.g.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix="datasource.mine")
|
||||
public DataSource dataSource() {
|
||||
return new FancyDataSource();
|
||||
}
|
||||
----
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
datasource.mine.jdbcUrl=jdbc:h2:mem:mydb
|
||||
datasource.mine.user=sa
|
||||
datasource.mine.poolSize=30
|
||||
----
|
||||
|
||||
|
||||
See '<<spring-boot-features.adoc#boot-features-configure-datasource>>' in the
|
||||
``Spring Boot features'' section and the
|
||||
{sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[`DataSourceAutoConfiguration`]
|
||||
class for more details.
|
||||
|
||||
[[howto-two-datasources]]
|
||||
=== Configure Two DataSources
|
||||
Creating more than one data source works the same as creating the first one.
|
||||
You might want to mark one of them as `@Primary` if you are using the default
|
||||
auto-configuration for JDBC or JPA (then that one will be picked up by any
|
||||
`@Autowired` injections).
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
@Bean
|
||||
@Primary
|
||||
@ConfigurationProperties(prefix="datasource.primary")
|
||||
public DataSource primaryDataSource() {
|
||||
return new FancyDataSource();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix="datasource.secondary")
|
||||
public DataSource secondaryDataSource() {
|
||||
return new FancyDataSource();
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[howto-use-spring-data-repositories]]
|
||||
|
|
@ -998,15 +1041,57 @@ and {sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[`JpaBas
|
|||
for more details.
|
||||
|
||||
|
||||
|
||||
[[howto-use-custom-entity-manager]]
|
||||
=== Use a custom EntityManagerFactory
|
||||
To take full control of the configuration of the `EntityManagerFactory`, you need to add
|
||||
a `@Bean` named "entityManagerFactory". To avoid eager initialization of JPA
|
||||
infrastructure, Spring Boot auto-configuration does not switch on its entity manager
|
||||
based on the presence of a bean of that type. Instead it has to do it by name.
|
||||
a `@Bean` named "entityManagerFactory". Spring Boot auto-configuration switches off its entity manager
|
||||
based on the presence of a bean of that type.
|
||||
|
||||
|
||||
[[howto-use-two-entity-managers]]
|
||||
=== Use Two EntityManagers
|
||||
|
||||
Even if the default `EntityManagerFactory` works fine, you will need
|
||||
to define a new one because otherwise the presence of the second bean
|
||||
of that type will switch off the default. To make it easy to do that
|
||||
you can use the convenient `EntityManagerBuilder` provided by Spring
|
||||
Boot, or if you prefer you can just use the
|
||||
`LocalContainerEntityManagerFactoryBean` directly from Spring ORM.
|
||||
Example:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
// add two data sources configured as above
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
|
||||
EntityManagerFactoryBuilder builder) {
|
||||
return builder
|
||||
.dataSource(customerDataSource())
|
||||
.packages(Customer.class)
|
||||
.persistenceUnit("customers")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
|
||||
EntityManagerFactoryBuilder builder) {
|
||||
return builder
|
||||
.dataSource(orderDataSource())
|
||||
.packages(Order.class)
|
||||
.persistenceUnit("orders")
|
||||
.build();
|
||||
}
|
||||
|
||||
----
|
||||
|
||||
The configuration above almost works on its own. To complete the
|
||||
picture you need to configure `TransactionManagers` for the two
|
||||
`EntityManagers` as well. One of them could be picked up by the
|
||||
default `JpaTransactionManager` in Spring Boot if you mark it as
|
||||
`@Primary`. The other would have to be explicitly injected into a new
|
||||
instance. Or you might be able to use a JTA transaction manager
|
||||
spanning both.
|
||||
|
||||
[[howto-use-traditional-persistence-xml]]
|
||||
=== Use a traditional persistence.xml
|
||||
|
|
|
|||
|
|
@ -1392,7 +1392,7 @@ following to your `application.properties`.
|
|||
NOTE: Hibernate's own internal property name for this (if you happen to remember it
|
||||
better) is `hibernate.hbm2ddl.auto`. You can set it, along with other Hibernate native
|
||||
properties, using `spring.jpa.properties.*` (the prefix is stripped before adding them
|
||||
to the entity manager). Alternatively, `spring.jpa.generate-ddl=false` switches off all
|
||||
to the entity manager). Also, `spring.jpa.generate-ddl=false` switches off all
|
||||
DDL generation.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@
|
|||
<verbose>true</verbose>
|
||||
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
|
||||
<generateGitPropertiesFile>true</generateGitPropertiesFile>
|
||||
<generateGitPropertiesFilename>src/main/resources/git.properties</generateGitPropertiesFilename>
|
||||
<generateGitPropertiesFilename>${basedir}/src/main/resources/git.properties</generateGitPropertiesFilename>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Support our own plugin -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue