001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.orm.jpa; 018 019import java.util.Collection; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.function.Supplier; 023 024import org.hibernate.cfg.AvailableSettings; 025 026import org.springframework.boot.context.properties.ConfigurationProperties; 027import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; 028import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; 029import org.springframework.util.Assert; 030import org.springframework.util.ObjectUtils; 031import org.springframework.util.StringUtils; 032 033/** 034 * Configuration properties for Hibernate. 035 * 036 * @author Stephane Nicoll 037 * @since 2.1.0 038 * @see JpaProperties 039 */ 040@ConfigurationProperties("spring.jpa.hibernate") 041public class HibernateProperties { 042 043 private final Naming naming = new Naming(); 044 045 /** 046 * DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. 047 * Defaults to "create-drop" when using an embedded database and no schema manager was 048 * detected. Otherwise, defaults to "none". 049 */ 050 private String ddlAuto; 051 052 /** 053 * Whether to use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. 054 * This is actually a shortcut for the "hibernate.id.new_generator_mappings" property. 055 * When not specified will default to "true". 056 */ 057 private Boolean useNewIdGeneratorMappings; 058 059 public String getDdlAuto() { 060 return this.ddlAuto; 061 } 062 063 public void setDdlAuto(String ddlAuto) { 064 this.ddlAuto = ddlAuto; 065 } 066 067 public Boolean isUseNewIdGeneratorMappings() { 068 return this.useNewIdGeneratorMappings; 069 } 070 071 public void setUseNewIdGeneratorMappings(Boolean useNewIdGeneratorMappings) { 072 this.useNewIdGeneratorMappings = useNewIdGeneratorMappings; 073 } 074 075 public Naming getNaming() { 076 return this.naming; 077 } 078 079 /** 080 * Determine the configuration properties for the initialization of the main Hibernate 081 * EntityManagerFactory based on standard JPA properties and 082 * {@link HibernateSettings}. 083 * @param jpaProperties standard JPA properties 084 * @param settings the settings to apply when determining the configuration properties 085 * @return the Hibernate properties to use 086 */ 087 public Map<String, Object> determineHibernateProperties( 088 Map<String, String> jpaProperties, HibernateSettings settings) { 089 Assert.notNull(jpaProperties, "JpaProperties must not be null"); 090 Assert.notNull(settings, "Settings must not be null"); 091 return getAdditionalProperties(jpaProperties, settings); 092 } 093 094 private Map<String, Object> getAdditionalProperties(Map<String, String> existing, 095 HibernateSettings settings) { 096 Map<String, Object> result = new HashMap<>(existing); 097 applyNewIdGeneratorMappings(result); 098 getNaming().applyNamingStrategies(result); 099 String ddlAuto = determineDdlAuto(existing, settings::getDdlAuto); 100 if (StringUtils.hasText(ddlAuto) && !"none".equals(ddlAuto)) { 101 result.put(AvailableSettings.HBM2DDL_AUTO, ddlAuto); 102 } 103 else { 104 result.remove(AvailableSettings.HBM2DDL_AUTO); 105 } 106 Collection<HibernatePropertiesCustomizer> customizers = settings 107 .getHibernatePropertiesCustomizers(); 108 if (!ObjectUtils.isEmpty(customizers)) { 109 customizers.forEach((customizer) -> customizer.customize(result)); 110 } 111 return result; 112 } 113 114 private void applyNewIdGeneratorMappings(Map<String, Object> result) { 115 if (this.useNewIdGeneratorMappings != null) { 116 result.put(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, 117 this.useNewIdGeneratorMappings.toString()); 118 } 119 else if (!result.containsKey(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS)) { 120 result.put(AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true"); 121 } 122 } 123 124 private String determineDdlAuto(Map<String, String> existing, 125 Supplier<String> defaultDdlAuto) { 126 String ddlAuto = existing.get(AvailableSettings.HBM2DDL_AUTO); 127 if (ddlAuto != null) { 128 return ddlAuto; 129 } 130 return (this.ddlAuto != null) ? this.ddlAuto : defaultDdlAuto.get(); 131 } 132 133 public static class Naming { 134 135 /** 136 * Fully qualified name of the implicit naming strategy. 137 */ 138 private String implicitStrategy; 139 140 /** 141 * Fully qualified name of the physical naming strategy. 142 */ 143 private String physicalStrategy; 144 145 public String getImplicitStrategy() { 146 return this.implicitStrategy; 147 } 148 149 public void setImplicitStrategy(String implicitStrategy) { 150 this.implicitStrategy = implicitStrategy; 151 } 152 153 public String getPhysicalStrategy() { 154 return this.physicalStrategy; 155 } 156 157 public void setPhysicalStrategy(String physicalStrategy) { 158 this.physicalStrategy = physicalStrategy; 159 } 160 161 private void applyNamingStrategies(Map<String, Object> properties) { 162 applyNamingStrategy(properties, AvailableSettings.IMPLICIT_NAMING_STRATEGY, 163 this.implicitStrategy, SpringImplicitNamingStrategy.class.getName()); 164 applyNamingStrategy(properties, AvailableSettings.PHYSICAL_NAMING_STRATEGY, 165 this.physicalStrategy, SpringPhysicalNamingStrategy.class.getName()); 166 } 167 168 private void applyNamingStrategy(Map<String, Object> properties, String key, 169 Object strategy, Object defaultStrategy) { 170 if (strategy != null) { 171 properties.put(key, strategy); 172 } 173 else if (defaultStrategy != null && !properties.containsKey(key)) { 174 properties.put(key, defaultStrategy); 175 } 176 } 177 178 } 179 180}