起因:
- spring data jpa多數(shù)據(jù)源配置可以參考Jpa多數(shù)據(jù)源配置蒋院,我就是參考這篇文章配置好的。
- 我的數(shù)據(jù)源有兩個(gè)剑肯,一個(gè)是mysql捧毛,一個(gè)是sqlserver。
- mysql數(shù)據(jù)庫(kù)的表字段形式采用的是jpa默認(rèn)的命名策略让网,實(shí)體屬性采用
currentUserName
形式的駝峰命名呀忧,映射時(shí)自動(dòng)將大寫轉(zhuǎn)換為小寫,并用_(下劃線)連接溃睹,即current_user_name
而账。 - 但是sqlserver數(shù)據(jù)庫(kù)中表中字段的命名為CurrentUserName這種形式。所以在映射的時(shí)候會(huì)報(bào)異常--無(wú)效的列名因篇。即使在相關(guān)實(shí)體的字段上添加
@column
注解泞辐,但是仍然無(wú)效。 - 經(jīng)過(guò)查找資料竞滓,原因是因?yàn)閖pa默認(rèn)的命名策略為
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
咐吼,采用這種命名策略,@column
注解會(huì)失效商佑。網(wǎng)上的解決辦法都是單數(shù)據(jù)源的配置锯茄,都不能解決我當(dāng)前項(xiàng)目遇到的問(wèn)題。 - 無(wú)奈只能自己解決茶没。
解決辦法
- 依照上面的參考文章肌幽,多數(shù)據(jù)源配置中有這么一段代碼,如下:
//注入JPA配置實(shí)體
@Autowired
private JpaProperties jpaProperties;
//獲取jpa配置信息
private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
- 在
return jpaProperties.getHibernateProperties(dataSource);
這段代碼前加上以下代碼:
jpaProperties.getHibernate().getNaming().setPhysicalStrategy("org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
即:
//獲取jpa配置信息
private Map<String, String> getVendorProperties(DataSource dataSource) {
jpaProperties.getHibernate().getNaming().setPhysicalStrategy("org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
return jpaProperties.getHibernateProperties(dataSource);
}
- jpa的默認(rèn)配置有兩個(gè)抓半,可以根據(jù)需要做選擇:
//spring物理命名策略--不對(duì)屬性名做任何改變
private static final String DEFAULT_PHYSICAL_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy";
//spring隱式命名策略--對(duì)屬性名做下劃線連接處理喂急,并將大寫改為小寫
private static final String DEFAULT_IMPLICIT_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy";
- jpa默認(rèn)的命名策略不能夠滿足可以自定義命名策略,網(wǎng)上有相關(guān)的示例琅关,不再贅述煮岁。
我們看下這句配置所涉及的源碼:
-
Hibernate
和Naming
是JpaProperties
的兩個(gè)內(nèi)部類
@ConfigurationProperties(prefix = "spring.jpa")
public class JpaProperties {
......省略
private Hibernate hibernate = new Hibernate();
public Hibernate getHibernate() {
return this.hibernate;
}
......省略
......省略
public static class Hibernate {
private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id."
+ "new_generator_mappings";
public Naming getNaming() {
return this.naming;
}
......省略
}
......省略
public static class Naming {
private static final String DEFAULT_PHYSICAL_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy";
private static final String DEFAULT_IMPLICIT_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy";
/**
* Fully qualified name of the physical naming strategy.
*/
private String physicalStrategy;
public void setPhysicalStrategy(String physicalStrategy) {
this.physicalStrategy = physicalStrategy;
}
private void applyNamingStrategies(Map<String, String> properties) {
applyNamingStrategy(properties, "hibernate.implicit_naming_strategy",
this.implicitStrategy, DEFAULT_IMPLICIT_STRATEGY);
applyNamingStrategy(properties, "hibernate.physical_naming_strategy",
this.physicalStrategy, DEFAULT_PHYSICAL_STRATEGY);
}
private void applyNamingStrategy(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);
}
}
......省略
}
}
- 通過(guò)連續(xù)的調(diào)用獲取到
Naming
對(duì)象,設(shè)置命名策略的屬性physicalStrategy
就在此對(duì)象中涣易。 - 在
return jpaProperties.getHibernateProperties(dataSource);
最后返回的這句中,最終會(huì)去調(diào)用applyNamingStrategies()
此方法冶伞,我們?cè)谏弦徊揭呀?jīng)將strategy
設(shè)置過(guò)了新症,在applyNamingStrategy()
這個(gè)方法中會(huì)去判斷,它不為空响禽,就會(huì)將此put
進(jìn)properties
中去徒爹。如果我們不去配置這個(gè)策略荚醒,如源碼所示,它會(huì)設(shè)置默認(rèn)的命名策略隆嗅。
如有錯(cuò)誤界阁,歡迎指正。