我正在使用使用Hibernate 5.0.11的Spring Boot 1.4.1。最初,我使用application.properties如下配置数据源:
application.properties
spring.datasource.uncle.url=jdbc:jtds:sqlserver://hostname:port/db spring.datasource.uncle.username=user spring.datasource.uncle.password=password spring.datasource.uncle.dialect=org.hibernate.dialect.SQLServer2012Dialect spring.datasource.uncle.driverClassName=net.sourceforge.jtds.jdbc.Driver
我将其配置为“ uncle”,因为这将是我将配置的多个数据源之一的名称。根据Spring文档,我像这样配置了此数据源:
@Bean @Primary @ConfigurationProperties(prefix = "spring.datasource.uncle") public DataSource uncleDataSource() { return DataSourceBuilder.create().build(); }
此时一切正常。
我创建了一个@Entity没有任何@Column注释的类,并让Hibernate找出列名,例如,如果我有一个名为Java的属性idBank,则Hibernate将自动假定列名为id_bank。这在生成ddl,运行SQL语句等时使用。我想利用此功能,因为我将有很多实体类,并且不想创建和维护所有@Column注释。在这一点上,这很好。
@Entity
@Column
idBank
id_bank
然后,我添加了另一个数据源,如下所示:
spring.datasource.aunt.url=jdbc:sybase:Tds:host2:port/db2 spring.datasource.aunt.username=user2 spring.datasource.aunt.password=password2 spring.datasource.aunt.dialect=org.hibernate.dialect.SybaseDialect spring.datasource.aunt.driverClassName=com.sybase.jdbc4.jdbc.SybDriver
…以及遵循Spring文档设置多个数据源的方法。显然,一旦定义了第二个数据源,它就无法配置默认Bean,而您必须定义自己的EntityManager和TransactionManager。因此,除了上面配置的数据源之外,我还添加了以下配置:
EntityManager
TransactionManager
@Bean @Primary PlatformTransactionManager uncleTransactionManager(@Qualifier("uncleEntityManagerFactory") final EntityManagerFactory factory) { return new JpaTransactionManager(factory); } @Bean @Primary LocalContainerEntityManagerFactoryBean uncleEntityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(uncleDataSource()) .packages(Uncle.class) .persistenceUnit("uncle") .build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.aunt") public DataSource auntDataSource() { return DataSourceBuilder.create().build(); } @Bean PlatformTransactionManager auntTransactionManager(@Qualifier("auntEntityManagerFactory") final EntityManagerFactory factory) { return new JpaTransactionManager(factory); } @Bean LocalContainerEntityManagerFactoryBean auntEntityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(auntDataSource()) .packages(Aunt.class) .persistenceUnit("aunt") .build(); }
这在连接数据库和尝试获取数据方面起作用。
但是 (这里是问题,感谢您阅读本文)。在完成这些配置后,我失去了将Java列名转换为蛇型名称的隐式命名策略,因此,现在如果我具有Java属性,idBank它会错误地使用列名idBank而不是id_bank。我真的很想找回该功能。
有一个JPA属性,spring.jpa.hibernate.naming- strategy在Spring和Hibernate中有各种命名策略类,如org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy。所以我尝试这样设置:
spring.jpa.hibernate.naming- strategy
org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
spring.jpa.hibernate.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
但这没有用。我尝试了一些变体,例如:
spring.datasource.uncle.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
和
spring.datasource.uncle.hibernate.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
但这没有任何效果。
然后我读到在Hibernate 5中,命名策略被分为两个部分:“物理”和“隐式”,每个都有不同的设置。所以我尝试了一下,有一些变化:
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.datasource.uncle.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.datasource.uncle..hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
但是这些都不起作用。
似乎应该有一种方法可以让我直接在Bean中设置此配置,例如在上SessionFactory,但是我找不到该API。关于此的文档似乎有一些空白。
SessionFactory
我真的很想避免同时设置一个persistence.xml,到目前为止我还不需要。
persistence.xml
所以这是我遇到的困难,希望有人能帮忙。我真正想要的是一种调试这些属性设置的方法,我同时打开了两者的跟踪日志记录org.springframework,org.hibernate但是那里没有任何用处。在配置这些bean时,我尝试单步执行代码,但是找不到发生这种情况的位置。如果有人拥有该信息并可以分享,我将非常感激。
org.springframework
org.hibernate
我遇到了同样的问题,并使用以下代码(针对问题的代码进行了修改-适用于单个实体管理器)进行了修复:
protected Map<String, Object> jpaProperties() { Map<String, Object> props = new HashMap<>(); props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName()); props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName()); return props; } @Primary @Bean(name = "defaultEntityManager") public LocalContainerEntityManagerFactoryBean defaultEntityManagerFactory( EntityManagerFactoryBuilder builder) { return builder .dataSource(auntDataSource()) .packages(Aunt.class) .persistenceUnit("aunt") .properties(jpaProperties()) .build(); }