轉(zhuǎn)載請注明出處:https://www.cnblogs.com/funnyzpc/p/9190226.html May 12, 2018 星期六,那是個晴天,,天湛藍(lán)湛藍(lán)的非常干凈,,仿佛飄過一粒塵埃也能看得清清楚楚,然后就發(fā)生了些事情,。,。。很傷心很難過,,至今也沒能抹去,,欸,我是怎樣一步步把自己變成這個樣子呢,。 難過的事情總會在縈繞很久,,罷了,這里還是不回憶了,就這樣吧,。 首先我說說這次配置多數(shù)據(jù)源的原因吧:原因大致有二: 一是我們的線上的有兩大業(yè)務(wù)系統(tǒng)云像系統(tǒng)和線上交易系統(tǒng),,這兩個系統(tǒng)的分別使用各自的mysql實例,交合業(yè)務(wù)的情況下目前通過定時腳本做數(shù)據(jù)更新和同步,,遂在開發(fā)新的業(yè)務(wù)模塊的時候就想到了將springboot配置兩個數(shù)據(jù)源(mysql和mysql) 二是最近在改造數(shù)據(jù)庫日志表的時候發(fā)現(xiàn)mysql的優(yōu)化捉襟見肘,,遂就想到了換數(shù)據(jù)庫,換個我個人研究了許久的PostgreSQL,,老大一開始不怎么樂意這么干,,但是看我又研究了這么久,性能也確實較mysql高許多,,再加上公司技術(shù)團(tuán)隊并不是很大的情況下(主要是業(yè)務(wù)量上去了數(shù)據(jù)庫性能跟不上,,也沒有獨立的DBA來維護(hù)和調(diào)優(yōu)Mysql),就給了我一周的時間研究數(shù)據(jù)庫(下次具體聊),,故就涉及到兩個數(shù)據(jù)源(mysql和PostgreSQL)的問題,。 嗯,對于以上兩個問題,,我嘗試了差異化的解決方式,,對于mysl和mysql數(shù)據(jù)源我選擇的是 阿里Druid+TK.Mybatis的解決方式,對于mysql和PG數(shù)據(jù)源我選擇的是Hikari+TK.Mybatis的解決方式.這兩種方式在實際配置中是有些許差異的,,這里我略去不講,,只講第二種,首先羅列下這其中碰到的問題: A>DataSource和SessionFactory引用指定注入問題,。 B>Hikari數(shù)據(jù)源配置參數(shù)名稱差異問題,。 C>Springboot init時配置類先后順序的問題 D>多數(shù)據(jù)源下Mybatis Mapper類重復(fù)問題 我先講講我大致的配置過程吧,首先新建立兩個配置類,,以隔離開(剛在一個包 中不隔離開也可以): 然后在兩個包中分別新建兩個配置類,,一個是MyBatis配置類和數(shù)據(jù)源、session工廠配置類,,我這里是這樣子: 這時候,,我先展示下數(shù)據(jù)源配置類: 1 package **.task.config.mysql;
2
3
4 import com.github.pagehelper.PageHelper;
5 import com.zaxxer.hikari.HikariConfig;
6 import com.zaxxer.hikari.HikariDataSource;
7 import org.apache.commons.lang3.StringUtils;
8 import org.apache.ibatis.plugin.Interceptor;
9 import org.apache.ibatis.session.SqlSessionFactory;
10 import org.mybatis.spring.SqlSessionFactoryBean;
11 import org.mybatis.spring.SqlSessionTemplate;
12 import org.springframework.beans.factory.annotation.Qualifier;
13 import org.springframework.beans.factory.annotation.Value;
14 import org.springframework.boot.context.properties.ConfigurationProperties;
15 import org.springframework.context.annotation.Bean;
16 import org.springframework.context.annotation.Configuration;
17 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
18 import org.springframework.core.io.support.ResourcePatternResolver;
19 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
20 import org.springframework.transaction.annotation.EnableTransactionManagement;
21
22 import javax.sql.DataSource;
23 import java.sql.SQLException;
24 import java.util.Properties;
25
26 /**
27 * mybatis 配置數(shù)據(jù)源類
28 *
29 * @author
30 * @date 2016年12月15日
31 * @since 1.7
32 */
33 @Configuration("mysqlCfg")
34 @EnableTransactionManagement
35 @ConfigurationProperties(prefix = "spring.db_mysql") //引用配置文件參數(shù)前綴
36 public class MybatisConfiguration extends HikariConfig {
37 @Value("${mybatis.mysql.xmlLocation}")
38 private String xmlLocation;
39
40 private String typeAliasesPackage;
41 //配置數(shù)據(jù)源
42 @Bean("mysqlDataSource")
43 public DataSource dataSource(){
44 /*
45 HikariDataSource ds=HikariDataSource();
46 ds.setJdbcUrl();
47 ds.setConnectionTimeout();
48 */
49 return new HikariDataSource(this);
50 }
51 //配置Session工廠
52 @Bean(name = "mysqlSqlSessionFactory")
53 public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("mysqlDataSource")DataSource dataSource) {
54 SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
55 bean.setDataSource(dataSource);
56 if(StringUtils.isNotBlank(typeAliasesPackage)){
57 bean.setTypeAliasesPackage(typeAliasesPackage);
58 }
59 //分頁插件
60 PageHelper pageHelper = new PageHelper();
61 Properties properties = new Properties();
62 properties.setProperty("reasonable", "true");
63 properties.setProperty("supportMethodsArguments", "true");
64 properties.setProperty("returnPageInfo", "check");
65 properties.setProperty("params", "count=countSql");
66 pageHelper.setProperties(properties);
67 //添加XML目錄
68 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
69 Interceptor[] plugins = new Interceptor[]{pageHelper};
70 bean.setPlugins(plugins);
71 try {
72
73 bean.setMapperLocations(resolver.getResources(xmlLocation));
74 return bean.getObject();
75 } catch (Exception e) {
76 e.printStackTrace();
77 throw new RuntimeException(e);
78 }
79 }
80 //mybatis會用到的SqlSession模板
81 @Bean
82 public SqlSessionTemplate sqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
83 return new SqlSessionTemplate(sqlSessionFactory);
84 }
85 //數(shù)據(jù)源事物配置
86 @Bean
87 public DataSourceTransactionManager transactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
88 return new DataSourceTransactionManager(dataSource);
89 }
90
91 }
在這里需要說明的是我通過繼承HikariConfig來配置數(shù)據(jù)源以及Session工廠,配置DataSource和Session工廠的時候需要使用指定注解名稱,,在這里是“mysqlDataSource“和”mysqlSqlSessionFactory“,,如果項目只有一個數(shù)據(jù)源的話大可不必寫這個的,另外需要特別注意的是在配置session工廠一定要在形式參數(shù)前使用@Qualifier注解引用指定的數(shù)據(jù)源,,同時SqlSession模板和事物也需要通過@Qualifier注解指定session工廠和數(shù)據(jù)源,,這里這樣做的原因是為了解決多數(shù)據(jù)源配置引用不明的問題。 OK,,數(shù)據(jù)源配置完成了,,現(xiàn)在將配置第二個配置類Mybatis配置類,,以下是具體配置內(nèi)容: 1 package **.task.config.mysql; 2 3 import org.springframework.boot.autoconfigure.AutoConfigureAfter; 4 import org.springframework.boot.bind.RelaxedPropertyResolver; 5 import org.springframework.context.EnvironmentAware; 6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Configuration; 8 import org.springframework.core.env.Environment; 9 import tk.mybatis.spring.mapper.MapperScannerConfigurer; 10 11 /** 12 * mybatis mapper 掃描配置類 13 * 14 * @author 15 * @date 2018年05月15日 16 */ 17 @Configuration("mysqlMapper") 18 @AutoConfigureAfter(MybatisConfiguration.class)//init時指定先后順序,這里是數(shù)據(jù)源在mybatis之前配置 19 public class MapperConfiguration implements EnvironmentAware { 20 21 private RelaxedPropertyResolver propertyResolver; 22 23 private String basePackage; 24 //這里為mybatis配置指定session工廠和Dao類基礎(chǔ)包路徑 25 @Bean("mysqlMapperScannerConfigurer") 26 public MapperScannerConfigurer mapperScannerConfigurer(Environment environment){ 27 28 MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); 29 mapperScannerConfigurer.setSqlSessionFactoryBeanName("mysqlSqlSessionFactory"); 30 mapperScannerConfigurer.setBasePackage(basePackage); 31 return mapperScannerConfigurer; 32 } 33 34 //設(shè)置環(huán)境變量(引用配置文件中的) 35 @Override 36 public void setEnvironment(Environment environment) { 37 this.propertyResolver = new RelaxedPropertyResolver(environment, null); 38 this.basePackage = propertyResolver.getProperty("mybatis.mysql.basepackage"); 39 } 40 } 配置Mybaits的時候需要將數(shù)據(jù)源配置置于之后配置,這里通過注解@AutoConfigureAfter來指定數(shù)據(jù)源配置類,,在配置Mybatis引用的Session工廠時也要指定為數(shù)據(jù)源配置類中的sqlSession工廠,,同時也需要指定生成的Mapper的包名,這個包的路徑這里我寫在application.yml的配置文件中,。 配置類已經(jīng)寫完,,現(xiàn)在最后一步了,在配置文件中指定配置類所引用的配置參數(shù),,大致是這樣子: spring:
application:
name: **-task
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
db_mysql:
name: DEV_MYSQL
#LOCAL
jdbc-url: jdbc:mysql://${MYSQL_HOST:192.168.10.141}:${MYSQL_PORT:3306}/p2p?useUnicode=true&characterEncoding=UTF8
driver-class-name: com.mysql.jdbc.Driver
username: p2p
password: p2p
# Hikari connection pool
type: com.zaxxer.hikari.HikariDataSource
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
pool-name: DatebookHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
validation-timeout: 10000
db_pg:
name: DEV_PG
# JDBC config
jdbc-url: jdbc:postgresql://192.168.10.141:5432/log
driver-class-name: org.postgresql.Driver
username: log
password: log
# Hikari connection pool
type: com.zaxxer.hikari.HikariDataSource
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
pool-name: DatebookHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
validation-timeout: 10000
以上配置文件中主要展示了數(shù)據(jù)源的一些配置(注意db_mysql和db_pg這兩項),,這里需要特別注意的是在Hikari數(shù)據(jù)源的配置參數(shù)中沒有url和driverClass,只有jdbc-url 和 driver-class-name這兩個,,其它的配置配置參數(shù)名稱與c3p0和Druid的無異,,具體的連接池大小需要根據(jù)實際的項目和數(shù)據(jù)庫服務(wù)器的硬件參數(shù)來配置,這里我只給出常見配置,。 哦,,對了,還需要在配置文件中追加Mybatis的配置參數(shù),,具體是這樣: 1 mybatis: 2 mysql: 3 basepackage: **.task.mapper.mysql 4 xmlLocation: classpath:mapper/mysql/*.xml 5 pg: 6 basepackage: **.task.mapper.pg 7 xmlLocation: classpath:mapper/pg/*.xml Mybatis的配置完成了,,對于PostgreSQL的配置只需要注意響應(yīng)的配置別名即可(比如數(shù)據(jù)源、session工廠,、SqlSession工廠等等) 本節(jié)所講的配置貌似已經(jīng)完成,,但是這里我順帶講一下我在性能測試的時候所遇見的兩個TK.mybatis這個插件的問題(原生mybatis也可能存在): A>對于兩個庫中存在同名的Mapper名字,在@Autowired使用時會產(chǎn)生沖突 B>持久化需要返回主鍵時對于mysql和PG兩中數(shù)據(jù)庫的處理方式存在差異 對于以上第一個問題(多數(shù)據(jù)源Mapper沖突),我給出的解決方式是在生成的Mapper類中指定沖突的那個Mapper的Service別名,,這樣: 1 package **.task.mapper.pg; 2 3 import com.github.carvechris.security.task.entity.pg.TestEmp; 4 import org.springframework.stereotype.Service; 5 import tk.mybatis.mapper.common.Mapper; 6 7 @Service("pgTestEmpMapper")//這里指定別名 8 public interface TestEmpMapper extends Mapper<TestEmp> { 9 } 這個Dao在使用的時候需要使用@Resource注解來指定的Dao類: 1 @Autowired
2 @Resource(name = "pgTestEmpMapper")
3 private **.task.mapper.pg.TestEmpMapper pgEmpMapper;
對于以上第二個問題(持久化返回主鍵問題),,mysql和pg的處理方式不同,,具體為: 對于mysql:需要在實體類中指定主鍵的生成方式,,即可在調(diào)用insert方法時返回生成的主鍵: /** * 表ID */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)//設(shè)置為主鍵自增以回寫主鍵 private Integer id; 以上的主鍵策略可以是主鍵表,也可以是UUID的方式,,根據(jù)項目實際需求而定,。 對于PG:首先需要在實體類的主鍵中這樣聲明: /** * 表ID */ @Id @Column(insertable=false)//指定主鍵為數(shù)據(jù)庫生成(同時需要在DB中將ID聲明為serial類型) private Long id; 再在Dao(生成的Mapper類中)聲明一個獨立的查入方法: 1 package **.task.mapper.pg; 2 3 import **.task.entity.pg.ZwPlBalancequery; 4 import org.apache.ibatis.annotations.InsertProvider; 5 import org.a2018-06-16pache.ibatis.annotations.Options; 6 import org.apache.ibatis.annotations.Select; 7 import tk.mybatis.mapper.common.Mapper; 8 import tk.mybatis.mapper.provider.base.BaseInsertProvider; 9 10 public interface ZwPlBalancequeryMapper extends Mapper<ZwPlBalancequery> { 11 //需要需要獨立聲明插入方法以返回插入記錄的ID 12 @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") 13 @InsertProvider(type = BaseInsertProvider.class, method = "dynamicSQL") 14 int insertWBack(ZwPlBalancequery record); 15 } 以上插入方法(insertWBack)中的注解是將id的生成方式改為數(shù)據(jù)庫生成,至此,,完美解決持久化返回記錄ID問題,。 現(xiàn)在是 2018-06-16 17:40:42 ,后天就是端午節(jié)了,,預(yù)祝各位節(jié)日快樂! |
|