spring boot 多資料庫配置問題
application.yml配置:
spring: jpa: show-sql: true application: name: xxx thymeleaf: cache: false #thymeleaf mode: LEGACYHTML5 datasource: oracle2: type: com.alibaba.druid.pool.DruidDataSource name: oracle2 # 初始化大小,最小,最大 initialSize: 5 # minIdle: 5 maxActive: 20 # 配置獲取連線等待超時的時間 maxWait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一個連線在池中最小生存的時間,單位是毫秒 minEvictableIdleTimeMillis: 40000 validationQuery: SELECT 1 FROM DUAL validationQueryTimeout: 10000 testWhileIdle: true testOnBorrow: false testOnReturn: false # 開啟PSCache,並且指定每個連線上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 filters: stat,wall # 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合併多個DruidDataSource的監控資料 useGlobalDataSourceStat: true driver-class-name: oracle.jdbc.driver.OracleDriver url: jdbc:oracle:thin:@192.168.1.102:1521:orcl username: xx password: xx oracle1: type: com.alibaba.druid.pool.DruidDataSource name: oracle1 # 初始化大小,最小,最大 initialSize: 5 minIdle: 5 maxActive: 20 # 配置獲取連線等待超時的時間 maxWait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一個連線在池中最小生存的時間,單位是毫秒 minEvictableIdleTimeMillis: 40000 validationQuery: SELECT 1 FROM DUAL validationQueryTimeout: 10000 testWhileIdle: true testOnBorrow: false testOnReturn: false # 開啟PSCache,並且指定每個連線上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 filters: stat,wall # 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合併多個DruidDataSource的監控資料 useGlobalDataSourceStat: true driver-class-name: oracle.jdbc.driver.OracleDriver url: "jdbc:oracle:thin:@192.168.1.103:1521:orcl" username: xx password: xx mysql1: type: com.alibaba.druid.pool.DruidDataSource # 初始化大小,最小,最大 name: mysql1 initialSize: 5 minIdle: 5 maxActive: 20 # 配置獲取連線等待超時的時間 maxWait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一個連線在池中最小生存的時間,單位是毫秒 minEvictableIdleTimeMillis: 30 validationQuery: SELECT 1 validationQueryTimeout: 10000 testWhileIdle: true testOnBorrow: false testOnReturn: false # 開啟PSCache,並且指定每個連線上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 filters: stat,wall # 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合併多個DruidDataSource的監控資料 useGlobalDataSourceStat: true driver-class-name: com.mysql.jdbc.Driver url: "jdbc:mysql://192.168.1.103:3306/lkjbase?useUnicode=true&characterEncoding=UTF-8" username: xx password: xx
DataSourcesConfig: @Configuration @EnableAutoConfiguration public class DataSourcesConfig { @Bean(name="oracle1DataSource") @Qualifier(value="oracle1DataSource") @ConfigurationProperties(prefix="spring.datasource.oracle1") public DataSource oracle1DataSource() { return new DruidDataSource(); } @Bean(name="oracle18DataSource") @Qualifier(value="oracle18DataSource") @ConfigurationProperties(prefix="spring.datasource.oracle2") public DataSource oracle18DataSource() { DruidDataSource datasource = new DruidDataSource(); return datasource; } @Primary @Bean(name="mysql1DataSource") @Qualifier(value="mysql1DataSource") @ConfigurationProperties(prefix="spring.datasource.mysql1") public DataSource mysql1DataSource() { return new DruidDataSource(); } } Mysql1DataSourceConfig: @Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryMysql1", //EntityManagerFactory引用 transactionManagerRef = "transactionManagerMysql1", //transactionManager引用 basePackages = {"com.dxt.cloud.mysql1.repository"}) //設定 基因網orderDiscountDataSource應用到的包 public class Mysql1DataSourceConfig {
@Autowired @Qualifier("mysql1DataSource") private DataSource mysql1DataSource;
/** * 注入JPA配置實體 */ @Autowired private JpaProperties jpaProperties; @Bean @Primary public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setGenerateDdl(true); adapter.setShowSql(true); return adapter; } /** * 通過呼叫JPA配置實體中的解析方法,解析datasource中各屬性的值 */ private Map<String,String> getVendorProperties( DataSource dataSource){ jpaProperties.setDatabase(Database.MYSQL); Map<String,String> map = new HashMap<>(); map.put("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect"); map.put("hibernate.hbm2ddl.auto","update"); jpaProperties.setProperties(map); return jpaProperties.getHibernateProperties(dataSource); }
/** * 配置EntityManagerFactory實體 * @param builder * @return 實體管理工廠 * packages 掃描@Entity註釋的軟體包名稱 * persistenceUnit 永續性單元的名稱。 如果只建立一個EntityManagerFactory,你可以省略這個,但是如果在同一個應用程式中有多個,你應該給它們不同的名字 * properties 標準JPA或供應商特定配置的通用屬性。 這些屬性覆蓋建構函式中提供的任何值。 * */ @Primary @Bean(name = "entityManagerFactoryMysql1") public LocalContainerEntityManagerFactoryBean entityManagerFactoryMysql1(EntityManagerFactoryBuilder builder){ return builder .dataSource(mysql1DataSource) .properties(getVendorProperties(mysql1DataSource)) .packages(new String[]{"com.dxt.cloud.mysql1.entity"}) .persistenceUnit("mysql1PersistenceUnit") .build(); } @Primary @Bean(name = "transactionManagerMysql1") public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager manager = new JpaTransactionManager(); manager.setEntityManagerFactory(entityManagerFactory); return manager; }
@Bean public BeanPostProcessor persistenceTranslation() { return new PersistenceAnnotationBeanPostProcessor(); }
/** * 配置EntityManager實體 * @param builder * @return 實體管理器 */ @Primary @Bean(name = "entityManagerMysql1") public EntityManager entityManager(EntityManagerFactoryBuilder builder){ return entityManagerFactoryMysql1(builder).getObject().createEntityManager(); }
/** * 配置事務transactionManager * @param builder * @return 事務管理器 */ @Primary @Bean(name = "transactionManagerMysql1") public PlatformTransactionManager transactionManagerMysql1(EntityManagerFactoryBuilder builder){ return new JpaTransactionManager(entityManagerFactoryMysql1(builder).getObject()); }
}
@Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryOracle1", //EntityManagerFactory引用 transactionManagerRef = "transactionManagerOracle1", //transactionManager引用 basePackages = {"com.dxt.cloud.oracle1.repository"}) public class Oracle1DataSourceConfig { @Autowired @Qualifier(value="oracle1DataSource") private DataSource oracle1DataSource;
/** * 注入JPA配置實體 */ @Autowired private JpaProperties jpaProperties; @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); // adapter.setDatabasePlatform("org.hibernate.dialect.OracleDialect"); return adapter; } /** * 通過呼叫JPA配置實體中的解析方法,解析datasource中各屬性的值 * @param dataSource 資料來源 * @return 本資料來源中各引數 */ private Map<String,String> getVendorProperties( DataSource dataSource){ jpaProperties.setDatabase(Database.ORACLE); jpaProperties.isShowSql(); Map<String,String> map = new HashMap<>(); jpaProperties.setProperties(map); Map<String, String> hibernateProperties = jpaProperties.getHibernateProperties(dataSource); return hibernateProperties; }
/** * 配置EntityManagerFactory實體 * @param builder * @return 實體管理工廠 * packages 掃描@Entity註釋的軟體包名稱 * persistenceUnit 永續性單元的名稱。 如果只建立一個EntityManagerFactory,你可以省略這個,但是如果在同一個應用程式中有多個,你應該給它們不同的名字 * properties 標準JPA或供應商特定配置的通用屬性。 這些屬性覆蓋建構函式中提供的任何值。 * */ @Bean(name = "entityManagerFactoryOracle1") public LocalContainerEntityManagerFactoryBean entityManagerFactoryOracle1(EntityManagerFactoryBuilder builder){ return builder .dataSource(oracle1DataSource) .properties(getVendorProperties(oracle1DataSource)) .packages(new String[]{"com.dxt.cloud.oracle1.entity"}) .persistenceUnit("oracle1PersistenceUnit") .build(); } @Bean(name = "transactionManagerOracle1") public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager manager = new JpaTransactionManager(); manager.setEntityManagerFactory(entityManagerFactory); return manager; }
@Bean public BeanPostProcessor persistenceTranslation() { return new PersistenceAnnotationBeanPostProcessor(); }
/** * 配置EntityManager實體 * @param builder * @return 實體管理器 */ @Bean(name = "entityManagerOracle1") public EntityManager entityManager(EntityManagerFactoryBuilder builder){ return entityManagerFactoryOracle1(builder).getObject().createEntityManager(); }
/** * 配置事務transactionManager * @param builder * @return 事務管理器 */ @Bean(name = "transactionManagerOracle1") public PlatformTransactionManager transactionManagerOracle1(EntityManagerFactoryBuilder builder){ return new JpaTransactionManager(entityManagerFactoryOracle1(builder).getObject()); } }
@Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryOracle18", //EntityManagerFactory引用 transactionManagerRef = "transactionManagerOracle1", //transactionManager引用 basePackages = {"com.dxt.cloud.oracle18.repository"}) public class Oracle18DataSourceConfig { @Autowired @Qualifier(value="oracle18DataSource") private DataSource oracle18DataSource;
/** * 注入JPA配置實體 */ @Autowired private JpaProperties jpaProperties; @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); return adapter; } /** * 通過呼叫JPA配置實體中的解析方法,解析datasource中各屬性的值 */ private Map<String,String> getVendorProperties( DataSource dataSource){ jpaProperties.setDatabase(Database.ORACLE); jpaProperties.isShowSql(); Map<String,String> map = new HashMap<>(); map.put("hibernate.physical_naming_strategy","org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"); jpaProperties.setProperties(map); Map<String, String> hibernateProperties = jpaProperties.getHibernateProperties(dataSource); return hibernateProperties; }
/** * 配置EntityManagerFactory實體 * @param builder * @return 實體管理工廠 * packages 掃描@Entity註釋的軟體包名稱 * persistenceUnit 永續性單元的名稱。 如果只建立一個EntityManagerFactory,你可以省略這個,但是如果在同一個應用程式中有多個,你應該給它們不同的名字 * properties 標準JPA或供應商特定配置的通用屬性。 這些屬性覆蓋建構函式中提供的任何值。 * */ @Bean(name = "entityManagerFactoryOracle18") public LocalContainerEntityManagerFactoryBean entityManagerFactoryOracle18(EntityManagerFactoryBuilder builder){ return builder .dataSource(oracle18DataSource) .properties(getVendorProperties(oracle18DataSource)) .packages(new String[]{"com.dxt.cloud.oracle18.entity"}) .persistenceUnit("oracle18PersistenceUnit") .build(); } @Bean(name = "transactionManagerOracle18") public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager manager = new JpaTransactionManager(); manager.setEntityManagerFactory(entityManagerFactory); return manager; }
@Bean public BeanPostProcessor persistenceTranslation() { return new PersistenceAnnotationBeanPostProcessor(); }
/** * 配置EntityManager實體 * @param builder * @return 實體管理器 */ @Bean(name = "entityManagerOracle18") public EntityManager entityManager(EntityManagerFactoryBuilder builder){ return entityManagerFactoryOracle18(builder).getObject().createEntityManager(); }
/** * 配置事務transactionManager * @param builder * @return 事務管理器 */ @Bean(name = "transactionManagerOracle18") public PlatformTransactionManager transactionManagerOracle18(EntityManagerFactoryBuilder builder){ return new JpaTransactionManager(entityManagerFactoryOracle1(builder).getObject()); } }
啟動日誌:
2018-11-04 07:47:16 [ERROR] - Properties configuration failed validation 2018-11-04 07:47:16 [ERROR] - Field error in object 'spring.datasource.oracle2' on field 'driverClassName': rejected value [oracle.jdbc.driver.OracleDriver]; codes [methodInvocation.spring.datasource.oracle2.driverClassName,methodInvocation.driverClassName,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.driverClassName,driverClassName]; arguments []; default message [driverClassName]]; default message [Property 'driverClassName' threw exception; nested exception is java.lang.UnsupportedOperationException] 2018-11-04 07:47:16 [ERROR] - Field error in object 'spring.datasource.oracle2' on field 'url': rejected value [jdbc:oracle:thin:@192.168.1.102:1521:orcl]; codes [methodInvocation.spring.datasource.oracle2.url,methodInvocation.url,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.url,url]; arguments []; default message [url]]; default message [Property 'url' threw exception; nested exception is java.lang.UnsupportedOperationException] 2018-11-04 07:47:16 [ERROR] - Field error in object 'spring.datasource.oracle2' on field 'username': rejected value [tj18d]; codes [methodInvocation.spring.datasource.oracle2.username,methodInvocation.username,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.username,username]; arguments []; default message [username]]; default message [Property 'username' threw exception; nested exception is java.lang.UnsupportedOperationException] 2018-11-04 07:47:16 [WARN] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'oracle18DataSource': Could not bind properties to DruidDataSource (prefix=spring.datasource.oracle2, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 3 errors Field error in object 'spring.datasource.oracle2' on field 'driverClassName': rejected value [oracle.jdbc.driver.OracleDriver]; codes [methodInvocation.spring.datasource.oracle2.driverClassName,methodInvocation.driverClassName,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.driverClassName,driverClassName]; arguments []; default message [driverClassName]]; default message [Property 'driverClassName' threw exception; nested exception is java.lang.UnsupportedOperationException] Field error in object 'spring.datasource.oracle2' on field 'url': rejected value [jdbc:oracle:thin:@192.168.1.102:1521:orcl]; codes [methodInvocation.spring.datasource.oracle2.url,methodInvocation.url,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.url,url]; arguments []; default message [url]]; default message [Property 'url' threw exception; nested exception is java.lang.UnsupportedOperationException] Field error in object 'spring.datasource.oracle2' on field 'username': rejected value [tj18d]; codes [methodInvocation.spring.datasource.oracle2.username,methodInvocation.username,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.datasource.oracle2.username,username]; arguments []; default message [username]]; default message [Property 'username' threw exception; nested exception is java.lang.UnsupportedOperationException]
*************************** APPLICATION FAILED TO START ***************************
Description:
Binding to target { CreateTime:"2018-11-04 07:47:06", ActiveCount:0, PoolingCount:0, CreateCount:1, DestroyCount:1, CloseCount:4, ConnectCount:4, Connections:[ ] } failed:
Property: spring.datasource.oracle2.driverClassName Value: oracle.jdbc.driver.OracleDriver Reason: Property 'driverClassName' threw exception; nested exception is java.lang.UnsupportedOperationException
Property: spring.datasource.oracle2.url Value: jdbc:oracle:thin:@192.168.1.102:1521:orcl Reason: Property 'url' threw exception; nested exception is java.lang.UnsupportedOperationException
Property: spring.datasource.oracle2.username Value: xx Reason: Property 'username' threw exception; nested exception is java.lang.UnsupportedOperationException
Action:
Update your application's configuration
問題說明:
1. 在配置mysql1和oracle1兩個資料庫時,專案正常啟動
2.配置三個資料庫啟動過程中,能夠在oracle2中查出資料,日誌中有列印:資料庫查詢zcptqbzw:1。已查出zcptqbzw表中有一條資料,表示資料庫連線沒有問題
3.從第一個Error看 [ERROR] - Properties configuration failed validation,在驗證配置上有問題