Skip to content

Commit

Permalink
Upgrade to Hibernate 5.1
Browse files Browse the repository at this point in the history
Upgrade to Hibernate 5.1, whilst still retaining compatibility with
Hibernate 4.3. This commit introduces the following changes:

* Add SpringPhysicalNamingStrategy to provides lowercase/underscore
  table names support. This should be equivalent to the previous
  SpringNamingStrategy that was used with Hibernate 4. No
  ImplicitNamingStrategy is provided since the Hibernate 5 defaults
  appear to be roughly equivalent to the conventions used in Spring
  Boot 1.3
  spring.jpa.hibernate.naming.

* Migrate  `spring.jpa.hibernate.naming-strategy` to
  `spring.jpa.hibernate.naming.strategy` and provide additional
  properties for physical and implicit.

* Add `spring.jpa.hibernate.use-new-id-generator-mappings` property and
  default to `false` when on Hibernate 5 to retain back compatibility.

See spring-projectsgh-2763
  • Loading branch information
philwebb committed Apr 6, 2016
1 parent 7fc990a commit 0db1194
Show file tree
Hide file tree
Showing 12 changed files with 596 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2012-2016 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 org.springframework.util.ClassUtils;

/**
* Supported Hibernate versions.
*
* @author Phillip Webb
*/
enum HibernateVersion {

/**
* Version 4.
*/
V4,

/**
* Version 5.
*/
V5;

private static final String HIBERNATE_5_CLASS = "org.hibernate.boot.model."
+ "naming.PhysicalNamingStrategy";

private static HibernateVersion running;

public static HibernateVersion getRunning() {
if (running == null) {
setRunning(ClassUtils.isPresent(HIBERNATE_5_CLASS, null) ? V5 : V4);
}
return running;
}

static void setRunning(HibernateVersion running) {
HibernateVersion.running = running;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
Expand All @@ -23,6 +23,7 @@

import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.util.StringUtils;

Expand All @@ -31,6 +32,7 @@
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
* @since 1.1.0
*/
@ConfigurationProperties(prefix = "spring.jpa")
Expand Down Expand Up @@ -125,12 +127,8 @@ public Map<String, String> getHibernateProperties(DataSource dataSource) {

public static class Hibernate {

private static final String DEFAULT_NAMING_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy";

/**
* Naming strategy fully qualified name.
*/
private Class<?> namingStrategy;
private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id."
+ "new_generator_mappings";

/**
* DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto"
Expand All @@ -139,12 +137,25 @@ public static class Hibernate {
*/
private String ddlAuto;

public Class<?> getNamingStrategy() {
return this.namingStrategy;
/**
* Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. This is
* actually a shortcut for the "hibernate.id.new_generator_mappings" property.
* When not specified will default to "false" with Hibernate 5 for back
* compatibility.
*/
private Boolean useNewIdGeneratorMappings;

private final Naming naming = new Naming();

@Deprecated
@DeprecatedConfigurationProperty(replacement = "spring.jpa.hibernate.naming.strategy")
public String getNamingStrategy() {
return getNaming().getStrategy();
}

public void setNamingStrategy(Class<?> namingStrategy) {
this.namingStrategy = namingStrategy;
@Deprecated
public void setNamingStrategy(String namingStrategy) {
getNaming().setStrategy(namingStrategy);
}

public String getDdlAuto() {
Expand All @@ -155,13 +166,23 @@ public void setDdlAuto(String ddlAuto) {
this.ddlAuto = ddlAuto;
}

public boolean isUseNewIdGeneratorMappings() {
return this.useNewIdGeneratorMappings;
}

public void setUseNewIdGeneratorMappings(boolean useNewIdGeneratorMappings) {
this.useNewIdGeneratorMappings = useNewIdGeneratorMappings;
}

public Naming getNaming() {
return this.naming;
}

private Map<String, String> getAdditionalProperties(Map<String, String> existing,
DataSource dataSource) {
Map<String, String> result = new HashMap<String, String>(existing);
if (!existing.containsKey("hibernate." + "ejb.naming_strategy_delegator")) {
result.put("hibernate.ejb.naming_strategy",
getHibernateNamingStrategy(existing));
}
applyNewIdGeneratorMappings(result);
getNaming().applyNamingStrategy(result);
String ddlAuto = getOrDeduceDdlAuto(existing, dataSource);
if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) {
result.put("hibernate.hbm2ddl.auto", ddlAuto);
Expand All @@ -172,12 +193,15 @@ private Map<String, String> getAdditionalProperties(Map<String, String> existing
return result;
}

private String getHibernateNamingStrategy(Map<String, String> existing) {
if (!existing.containsKey("hibernate." + "ejb.naming_strategy")
&& this.namingStrategy != null) {
return this.namingStrategy.getName();
private void applyNewIdGeneratorMappings(Map<String, String> result) {
if (this.useNewIdGeneratorMappings != null) {
result.put(USE_NEW_ID_GENERATOR_MAPPINGS,
this.useNewIdGeneratorMappings.toString());
}
else if (HibernateVersion.getRunning() == HibernateVersion.V5
&& !result.containsKey(USE_NEW_ID_GENERATOR_MAPPINGS)) {
result.put(USE_NEW_ID_GENERATOR_MAPPINGS, "false");
}
return DEFAULT_NAMING_STRATEGY;
}

private String getOrDeduceDdlAuto(Map<String, String> existing,
Expand All @@ -203,4 +227,96 @@ private String getDefaultDdlAuto(DataSource dataSource) {

}

public static class Naming {

private static final String DEFAULT_HIBERNATE4_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy";

private static final String DEFAULT_PHYSICAL_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy";

/**
* Hibernate 5 implicit naming strategy fully qualified name.
*/
private String implicitStrategy;

/**
* Hibernate 5 physical naming strategy fully qualified name.
*/
private String physicalStrategy;

/**
* Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate
* 5.
*/
private String strategy;

public String getImplicitStrategy() {
return this.implicitStrategy;
}

public void setImplicitStrategy(String implicitStrategy) {
this.implicitStrategy = implicitStrategy;
}

public String getPhysicalStrategy() {
return this.physicalStrategy;
}

public void setPhysicalStrategy(String physicalStrategy) {
this.physicalStrategy = physicalStrategy;
}

public String getStrategy() {
return this.strategy;
}

public void setStrategy(String strategy) {
this.strategy = strategy;
}

private void applyNamingStrategy(Map<String, String> properties) {
switch (HibernateVersion.getRunning()) {
case V4:
applyHibernate4NamingStrategy(properties);
break;
case V5:
applyHibernate5NamingStrategy(properties);
break;
}
}

private void applyHibernate5NamingStrategy(Map<String, String> properties) {
applyHibernate5NamingStrategy(properties,
"hibernate.implicit_naming_strategy", this.implicitStrategy, null);
applyHibernate5NamingStrategy(properties,
"hibernate.physical_naming_strategy", this.physicalStrategy,
DEFAULT_PHYSICAL_STRATEGY);
}

private void applyHibernate5NamingStrategy(Map<String, String> properties,
String key, String strategy, String defaultStrategy) {
if (strategy != null) {
properties.put(key, strategy);
}
else if (defaultStrategy != null && !properties.containsKey(key)) {
properties.put(key, defaultStrategy);
}
}

private void applyHibernate4NamingStrategy(Map<String, String> properties) {
if (!properties.containsKey("hibernate.ejb.naming_strategy_delegator")) {
properties.put("hibernate.ejb.naming_strategy",
getHibernate4NamingStrategy(properties));
}
}

private String getHibernate4NamingStrategy(Map<String, String> existing) {
if (!existing.containsKey("hibernate.ejb.naming_strategy")
&& this.strategy != null) {
return this.strategy;
}
return DEFAULT_HIBERNATE4_STRATEGY;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,29 @@
]
},
{
"name": "spring.jpa.hibernate.naming-strategy",
"name": "spring.jpa.hibernate.naming.implicit-strategy",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "org.hibernate.boot.model.naming.ImplicitNamingStrategy"
}
}
]
},
{
"name": "spring.jpa.hibernate.naming.physical-strategy",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "org.hibernate.boot.model.naming.PhysicalNamingStrategy"
}
}
]
},
{
"name": "spring.jpa.hibernate.naming.strategy",
"providers": [
{
"name": "class-reference",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2016 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import javax.transaction.UserTransaction;

import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.junit.After;
import org.junit.Test;

import org.springframework.beans.factory.BeanCreationException;
Expand All @@ -49,6 +50,11 @@
public class HibernateJpaAutoConfigurationTests
extends AbstractJpaAutoConfigurationTests {

@After
public void cleanup() {
HibernateVersion.setRunning(null);
}

@Override
protected Class<?> getAutoConfigureClass() {
return HibernateJpaAutoConfiguration.class;
Expand Down Expand Up @@ -80,6 +86,7 @@ public void testDataScript() throws Exception {

@Test
public void testCustomNamingStrategy() throws Exception {
HibernateVersion.setRunning(HibernateVersion.V4);
EnvironmentTestUtils.addEnvironment(this.context,
"spring.jpa.hibernate.namingStrategy:"
+ "org.hibernate.cfg.EJB3NamingStrategy");
Expand All @@ -94,6 +101,7 @@ public void testCustomNamingStrategy() throws Exception {

@Test
public void testCustomNamingStrategyViaJpaProperties() throws Exception {
HibernateVersion.setRunning(HibernateVersion.V4);
EnvironmentTestUtils.addEnvironment(this.context,
"spring.jpa.properties.hibernate.ejb.naming_strategy:"
+ "org.hibernate.cfg.EJB3NamingStrategy");
Expand Down
Loading

0 comments on commit 0db1194

Please sign in to comment.