我已经浏览了有关如何设置的可用示例和教程 hibernate.dialect
属性正确,但没有找到适合我的情况的方法。
This教程最适合我,但它缺乏设置 hibernate.dialect
的能力动态属性,因为我有不同类型的数据库要连接:
由于方言不正确,我的 JPA(删除/更新)查询失败。
以下是
@Configuration
的实现,完美运行,我如何才能设置 hibernate.dialect
每个数据源在运行时动态? 先感谢您。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.multidb",
entityManagerFactoryRef = "multiEntityManager",
transactionManagerRef = "multiTransactionManager"
)
public class PersistenceConfiguration {
private final String PACKAGE_SCAN = "com.example.multidb";
@Primary
@Bean(name = "mainDataSource")
@ConfigurationProperties("app.datasource.main")
public DataSource mainDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "clientADataSource")
@ConfigurationProperties("app.datasource.clienta")
public DataSource clientADataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "clientBDataSource")
@ConfigurationProperties("app.datasource.clientb")
public DataSource clientBDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "multiRoutingDataSource")
public DataSource multiRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.MAIN, mainDataSource());
targetDataSources.put(DBTypeEnum.CLIENT_A, clientADataSource());
targetDataSources.put(DBTypeEnum.CLIENT_B, clientBDataSource());
MultiRoutingDataSource multiRoutingDataSource = new MultiRoutingDataSource();
multiRoutingDataSource.setDefaultTargetDataSource(mainDataSource());
multiRoutingDataSource.setTargetDataSources(targetDataSources);
return multiRoutingDataSource;
}
@Bean(name = "multiEntityManager")
public LocalContainerEntityManagerFactoryBean multiEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(multiRoutingDataSource());
em.setPackagesToScan(PACKAGE_SCAN);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
@Bean(name = "multiTransactionManager")
public PlatformTransactionManager multiTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
multiEntityManager().getObject());
return transactionManager;
}
@Primary
@Bean(name = "dbSessionFactory")
public LocalSessionFactoryBean dbSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(multiRoutingDataSource());
sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
//set hibernate.dialect for each datasource
return properties;
}
}
最佳答案
我已经为您创建了一个工作示例,我将在此处对其进行描述,但如果您想自己跳入代码 it's available at this GitHub repo .
就我而言,我创建了两个数据源,一个用于 User
另一个是 Item
.
这里的实体:
package com.marcosbarbero.so.multiple.ds.entity.user;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Entity
@Table(schema = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
@Column(unique = true, nullable = false)
private String email;
private int age;
}
package com.marcosbarbero.so.multiple.ds.entity.item;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Entity
@Table(schema = "item")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
}
请注意,为每个域设置不同的包很重要。
然后我创建了
Repositories
package com.marcosbarbero.so.multiple.ds.repository.user;
import com.marcosbarbero.so.multiple.ds.entity.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
}
package com.marcosbarbero.so.multiple.ds.repository.item;
import com.marcosbarbero.so.multiple.ds.entity.item.Item;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ItemRepository extends JpaRepository<Item, Integer> {
}
repo 没有什么特别之处。让我们转到最后一部分,即配置。
@ConfigurationProperties
类来具体化我的配置,请耐心等待,我知道命名不是最好的:) package com.marcosbarbero.so.multiple.ds.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Data
@Component
@ConfigurationProperties(prefix = "multi-datasource")
public class MultipleDataSourceProperties {
private UserDataSourceProperties user = new UserDataSourceProperties();
private ItemDataSourceProperties item = new ItemDataSourceProperties();
@Data
public static class UserDataSourceProperties {
private HibernateProperties hibernate = new HibernateProperties();
}
@Data
public static class ItemDataSourceProperties {
private HibernateProperties hibernate = new HibernateProperties();
}
@Data
public static class HibernateProperties {
private Map<String, String> properties = new HashMap<>();
}
}
我们很快就会看到属性配置文件。
DataSource
为 User
:package com.marcosbarbero.so.multiple.ds.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableJpaRepositories(
basePackages = "com.marcosbarbero.so.multiple.ds.repository.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager"
)
public class UserDataSourceConfig {
private final MultipleDataSourceProperties properties;
public UserDataSourceConfig(MultipleDataSourceProperties properties) {
this.properties = properties;
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean userEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan("com.marcosbarbero.so.multiple.ds.entity.user");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(properties.getUser().getHibernate().getProperties());
return em;
}
@Primary
@Bean
@ConfigurationProperties("multi-datasource.user")
public DataSource userDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Primary
@Bean
public PlatformTransactionManager userTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(userEntityManager().getObject());
return transactionManager;
}
}
这门课对你来说很重要的部分是
em.setJpaPropertyMap(properties.getUser().getHibernate().getProperties());
它从我们的 @ConfigurationProperties
获取用户的 Hibernate 配置属性。上面定义的类。Item
做同样的事情:package com.marcosbarbero.so.multiple.ds.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableJpaRepositories(
basePackages = "com.marcosbarbero.so.multiple.ds.repository.item",
entityManagerFactoryRef = "itemEntityManager",
transactionManagerRef = "itemTransactionManager"
)
public class ItemDataSourceConfig {
private final MultipleDataSourceProperties properties;
public ItemDataSourceConfig(MultipleDataSourceProperties properties) {
this.properties = properties;
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean itemEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(itemDataSource());
em.setPackagesToScan("com.marcosbarbero.so.multiple.ds.entity.item");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(properties.getItem().getHibernate().getProperties());
return em;
}
@Primary
@Bean
@ConfigurationProperties("multi-datasource.item")
public DataSource itemDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Primary
@Bean
public PlatformTransactionManager itemTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(itemEntityManager().getObject());
return transactionManager;
}
}
application.properties
multi-datasource.item.jdbcUrl=jdbc:h2:mem:spring_jpa_item;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS ITEM
multi-datasource.item.username=sa
multi-datasource.item.password=sa
multi-datasource.item.hibernate.properties.hibernate.hbm2ddl.auto=create-drop
multi-datasource.item.hibernate.properties.hibernate.cache.use_second_level_cache=false
multi-datasource.item.hibernate.properties.hibernate.cache.use_query_cache=false
multi-datasource.item.hibernate.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
multi-datasource.user.jdbcUrl=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USER
multi-datasource.user.username=sa
multi-datasource.user.password=sa
multi-datasource.user.hibernate.properties.hibernate.hbm2ddl.auto=create-drop
multi-datasource.user.hibernate.properties.hibernate.cache.use_second_level_cache=false
multi-datasource.user.hibernate.properties.hibernate.cache.use_query_cache=false
multi-datasource.user.hibernate.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect
package com.marcosbarbero.so;
import com.marcosbarbero.so.multiple.ds.entity.item.Item;
import com.marcosbarbero.so.multiple.ds.entity.user.User;
import com.marcosbarbero.so.multiple.ds.repository.item.ItemRepository;
import com.marcosbarbero.so.multiple.ds.repository.user.UserRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@SpringBootTest
public class JPAMultipleDBTest {
@Autowired
private UserRepository userRepository;
@Autowired
private ItemRepository itemRepository;
@Test
public void whenCreatingUser_thenCreated() {
User user = new User();
user.setName("John");
user.setEmail("john@test.com");
user.setAge(20);
user = userRepository.save(user);
assertNotNull(userRepository.findById(user.getId()));
}
@Test
public void whenCreatingProduct_thenCreated() {
Item item = new Item();
item.setName("Book");
item.setId(2);
item = itemRepository.save(item);
assertNotNull(itemRepository.findById(item.getId()));
}
}
我认为还值得一提的是,为了让它一切正常,我禁用了
DataSourceAutoConfiguration
,就这么简单:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
再说一遍,这一切都是 available at this GitHub repo .
关于java - 在 spring boot 中动态设置 hibernate.dialect 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60796798/