Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
guns-vip
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chenjunxiong
guns-vip
Commits
997656eb
Commit
997656eb
authored
Mar 18, 2019
by
fengshuonan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
强力集成atomikos,完美解决多数据源事务
parent
4594a330
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
229 additions
and
82 deletions
+229
-82
pom.xml
+8
-1
sql/guns_test_db.sql
+36
-0
src/main/java/cn/stylefeng/guns/config/datasource/multi/MultiDataSourceConfig.java
+32
-71
src/main/java/cn/stylefeng/guns/config/datasource/multi/MultiSqlSessionFactoryConfig.java
+143
-0
src/main/resources/application-dev.yml
+5
-5
src/main/resources/application-local.yml
+5
-5
No files found.
pom.xml
View file @
997656eb
...
...
@@ -40,7 +40,7 @@
<dependency>
<groupId>
cn.stylefeng.roses
</groupId>
<artifactId>
kernel-core
</artifactId>
<version>
1.
1.3
</version>
<version>
1.
2.0
</version>
</dependency>
<dependency>
...
...
@@ -154,6 +154,13 @@
<optional>
true
</optional>
</dependency>
<!-- 多数据源事务管理-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-jta-atomikos
</artifactId>
<optional>
true
</optional>
</dependency>
<!--需要分布式session的话需要放开注释-->
<!--<dependency>-->
<!--<groupId>org.springframework.session</groupId>-->
...
...
sql/guns_test_db.sql
0 → 100644
View file @
997656eb
/* 这个sql用在测试多数据源的时候,可以不用运行 */
DROP
DATABASE
IF
EXISTS
guns_test_db
;
CREATE
DATABASE
IF
NOT
EXISTS
guns_test_db
DEFAULT
CHARSET
utf8
COLLATE
utf8_general_ci
;
USE
guns_test_db
;
SET
NAMES
utf8mb4
;
SET
FOREIGN_KEY_CHECKS
=
0
;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_user`
;
CREATE
TABLE
`sys_user`
(
`USER_ID`
bigint
(
20
)
NOT
NULL
COMMENT
'主键id'
,
`AVATAR`
varchar
(
255
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'头像'
,
`ACCOUNT`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'账号'
,
`PASSWORD`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'密码'
,
`SALT`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'md5密码盐'
,
`NAME`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'名字'
,
`BIRTHDAY`
datetime
(
0
)
DEFAULT
NULL
COMMENT
'生日'
,
`SEX`
varchar
(
32
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'性别(字典)'
,
`EMAIL`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'电子邮件'
,
`PHONE`
varchar
(
45
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'电话'
,
`ROLE_ID`
varchar
(
255
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'角色id(多个逗号隔开)'
,
`DEPT_ID`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'部门id(多个逗号隔开)'
,
`STATUS`
varchar
(
32
)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
DEFAULT
NULL
COMMENT
'状态(字典)'
,
`CREATE_TIME`
datetime
(
0
)
DEFAULT
NULL
COMMENT
'创建时间'
,
`CREATE_USER`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'创建人'
,
`UPDATE_TIME`
datetime
(
0
)
DEFAULT
NULL
COMMENT
'更新时间'
,
`UPDATE_USER`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'更新人'
,
`VERSION`
int
(
11
)
DEFAULT
NULL
COMMENT
'乐观锁'
,
PRIMARY
KEY
(
`USER_ID`
)
USING
BTREE
)
ENGINE
=
InnoDB
CHARACTER
SET
=
utf8
COLLATE
=
utf8_general_ci
COMMENT
=
'管理员表'
ROW_FORMAT
=
Dynamic
;
\ No newline at end of file
src/main/java/cn/stylefeng/guns/config/datasource/MultiDataSourceConfig.java
→
src/main/java/cn/stylefeng/guns/config/datasource/
multi/
MultiDataSourceConfig.java
View file @
997656eb
...
...
@@ -13,25 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
cn
.
stylefeng
.
guns
.
config
.
datasource
;
package
cn
.
stylefeng
.
guns
.
config
.
datasource
.
multi
;
import
cn.stylefeng.roses.core.config.properties.DruidProperties
;
import
cn.stylefeng.roses.core.config.properties.MutiDataSourceProperties
;
import
cn.stylefeng.roses.core.datascope.DataScopeInterceptor
;
import
cn.stylefeng.roses.core.mutidatasource.DynamicDataSource
;
import
cn.stylefeng.roses.core.mutidatasource.aop.MultiSourceExAop
;
import
com.alibaba.druid.pool.DruidDataSource
;
import
com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor
;
import
com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor
;
import
cn.stylefeng.roses.core.util.ToolUtil
;
import
com.atomikos.jdbc.AtomikosDataSourceBean
;
import
org.mybatis.spring.annotation.MapperScan
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.
transaction.annotation.EnableTransactionManagement
;
import
org.springframework.
context.annotation.Primary
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
javax.sql.DataSource
;
/**
* 多数据源配置<br/>
...
...
@@ -43,14 +39,14 @@ import java.util.HashMap;
*/
@Configuration
@ConditionalOnProperty
(
prefix
=
"guns.muti-datasource"
,
name
=
"open"
,
havingValue
=
"true"
)
@EnableTransactionManagement
(
order
=
2
,
proxyTargetClass
=
true
)
@MapperScan
(
basePackages
=
{
"cn.stylefeng.guns.modular.*.mapper"
,
"cn.stylefeng.guns.multi.mapper"
})
@MapperScan
(
basePackages
=
{
"cn.stylefeng.guns.modular.*.mapper"
},
sqlSessionTemplateRef
=
"gunsSqlSessionTemplate"
)
public
class
MultiDataSourceConfig
{
/**
*
druid
配置
*
默认主数据源
配置
*/
@Bean
@Primary
@ConfigurationProperties
(
prefix
=
"spring.datasource"
)
public
DruidProperties
druidProperties
()
{
return
new
DruidProperties
();
...
...
@@ -61,84 +57,49 @@ public class MultiDataSourceConfig {
*/
@Bean
@ConfigurationProperties
(
prefix
=
"guns.muti-datasource"
)
public
MutiDataSource
Properties
mutiDataSourceProperties
()
{
return
new
MutiDataSource
Properties
();
public
Druid
Properties
mutiDataSourceProperties
()
{
return
new
Druid
Properties
();
}
/**
*
多数据源切换的aop
*
主数据源实例
*/
@Primary
@Bean
public
MultiSourceExAop
multiSourceExAop
()
{
return
new
MultiSourceExAop
();
}
/**
* guns的数据源
*/
private
DruidDataSource
dataSource
(
DruidProperties
druidProperties
)
{
DruidDataSource
dataSource
=
new
DruidDataSource
();
druidProperties
.
config
(
dataSource
);
return
dataSource
;
public
DataSource
dataSourcePrimary
(
@Qualifier
(
"druidProperties"
)
DruidProperties
druidProperties
)
{
if
(
ToolUtil
.
isOneEmpty
(
druidProperties
,
druidProperties
.
getDataSourceName
()))
{
throw
new
IllegalArgumentException
(
"初始化OptionalSqlSessionTemplate错误!请设置spring.datasource.data-source-name属性的值!"
);
}
/**
* 多数据源,第二个数据源
*/
private
DruidDataSource
bizDataSource
(
DruidProperties
druidProperties
,
MutiDataSourceProperties
mutiDataSourceProperties
)
{
DruidDataSource
dataSource
=
new
DruidDataSource
();
druidProperties
.
config
(
dataSource
);
mutiDataSourceProperties
.
config
(
dataSource
);
return
dataSource
;
return
createDataSource
(
druidProperties
.
getDataSourceName
(),
druidProperties
);
}
/**
*
多数据源连接池配置
*
第二个数据源实例
*/
@Bean
public
DynamicDataSource
mutiDataSource
(
DruidProperties
druidProperties
,
MutiDataSourceProperties
mutiDataSourceProperties
)
{
DruidDataSource
dataSourceGuns
=
dataSource
(
druidProperties
);
DruidDataSource
bizDataSource
=
bizDataSource
(
druidProperties
,
mutiDataSourceProperties
);
try
{
dataSourceGuns
.
init
();
bizDataSource
.
init
();
}
catch
(
SQLException
sql
)
{
sql
.
printStackTrace
();
}
DynamicDataSource
dynamicDataSource
=
new
DynamicDataSource
();
HashMap
<
Object
,
Object
>
hashMap
=
new
HashMap
<>();
hashMap
.
put
(
mutiDataSourceProperties
.
getDataSourceNames
()[
0
],
dataSourceGuns
);
hashMap
.
put
(
mutiDataSourceProperties
.
getDataSourceNames
()[
1
],
bizDataSource
);
dynamicDataSource
.
setTargetDataSources
(
hashMap
);
dynamicDataSource
.
setDefaultTargetDataSource
(
dataSourceGuns
);
return
dynamicDataSource
;
public
DataSource
dataSourceBusiness
(
@Qualifier
(
"mutiDataSourceProperties"
)
DruidProperties
mutiDataSourceProperties
)
{
if
(
ToolUtil
.
isOneEmpty
(
mutiDataSourceProperties
,
mutiDataSourceProperties
.
getDataSourceName
()))
{
throw
new
IllegalArgumentException
(
"初始化OptionalSqlSessionTemplate错误!请设置spring.muti-datasource.data-source-name属性的值!"
);
}
/**
* mybatis-plus分页插件
*/
@Bean
public
PaginationInterceptor
paginationInterceptor
()
{
return
new
PaginationInterceptor
();
return
createDataSource
(
mutiDataSourceProperties
.
getDataSourceName
(),
mutiDataSourceProperties
);
}
/**
*
数据范围mybatis插件
*
多数据源切换的aop
*/
@Bean
public
DataScopeInterceptor
dataScopeInterceptor
()
{
return
new
DataScopeInterceptor
();
public
MultiSourceExAop
multiSourceExAop
()
{
return
new
MultiSourceExAop
();
}
/**
*
乐观锁mybatis插件
*
数据源创建模板
*/
@Bean
public
OptimisticLockerInterceptor
optimisticLockerInterceptor
()
{
return
new
OptimisticLockerInterceptor
();
private
static
DataSource
createDataSource
(
String
dataSourceName
,
DruidProperties
druidProperties
)
{
AtomikosDataSourceBean
atomikosDataSourceBean
=
new
AtomikosDataSourceBean
();
atomikosDataSourceBean
.
setXaDataSourceClassName
(
"com.alibaba.druid.pool.xa.DruidXADataSource"
);
atomikosDataSourceBean
.
setUniqueResourceName
(
dataSourceName
);
atomikosDataSourceBean
.
setXaProperties
(
druidProperties
.
createProperties
());
return
atomikosDataSourceBean
;
}
}
src/main/java/cn/stylefeng/guns/config/datasource/multi/MultiSqlSessionFactoryConfig.java
0 → 100644
View file @
997656eb
/**
* Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
cn
.
stylefeng
.
guns
.
config
.
datasource
.
multi
;
import
cn.stylefeng.roses.core.config.properties.DruidProperties
;
import
cn.stylefeng.roses.core.datascope.DataScopeInterceptor
;
import
cn.stylefeng.roses.core.mutidatasource.mybatis.OptionalSqlSessionTemplate
;
import
cn.stylefeng.roses.core.util.ToolUtil
;
import
cn.stylefeng.roses.kernel.model.exception.ServiceException
;
import
com.baomidou.mybatisplus.autoconfigure.SpringBootVFS
;
import
com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor
;
import
com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor
;
import
com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.ibatis.plugin.Interceptor
;
import
org.apache.ibatis.session.SqlSessionFactory
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
javax.sql.DataSource
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 多数据源配置<br/>
* <p>
* 注:由于引入多数据源,所以让spring事务的aop要在多数据源切换aop的后面
*
* @author stylefeng
* @Date 2017/5/20 21:58
*/
@Slf4j
@Configuration
@ConditionalOnProperty
(
prefix
=
"guns.muti-datasource"
,
name
=
"open"
,
havingValue
=
"true"
)
public
class
MultiSqlSessionFactoryConfig
{
/**
* xml文件的位置,改包了注意修改哦
*/
public
static
final
String
MAPPING_XML_CLASSPATH
=
"classpath:cn/stylefeng/guns/modular/**/mapping/*.xml"
;
/**
* 主sqlSessionFactory
*/
@Primary
@Bean
public
SqlSessionFactory
sqlSessionFactoryPrimary
(
@Qualifier
(
"dataSourcePrimary"
)
DataSource
dataSource
)
{
return
createSqlSessionFactory
(
dataSource
);
}
/**
* 第二个sqlSessionFactory
*/
@Bean
public
SqlSessionFactory
sqlSessionFactoryBusiness
(
@Qualifier
(
"dataSourceBusiness"
)
DataSource
dataSource
)
{
return
createSqlSessionFactory
(
dataSource
);
}
/**
* 多数据源sqlSessionTemplate切换模板
*/
@Bean
(
name
=
"gunsSqlSessionTemplate"
)
public
OptionalSqlSessionTemplate
gunsSqlSessionTemplate
(
@Qualifier
(
"sqlSessionFactoryPrimary"
)
SqlSessionFactory
sqlSessionFactoryPrimary
,
@Qualifier
(
"sqlSessionFactoryBusiness"
)
SqlSessionFactory
sqlSessionFactoryBusiness
,
@Qualifier
(
"druidProperties"
)
DruidProperties
druidProperties
,
@Qualifier
(
"mutiDataSourceProperties"
)
DruidProperties
mutiDataSourceProperties
)
{
if
(
ToolUtil
.
isOneEmpty
(
druidProperties
,
druidProperties
.
getDataSourceName
()))
{
throw
new
IllegalArgumentException
(
"初始化OptionalSqlSessionTemplate错误!请设置spring.datasource.data-source-name属性的值!"
);
}
if
(
ToolUtil
.
isOneEmpty
(
mutiDataSourceProperties
,
mutiDataSourceProperties
.
getDataSourceName
()))
{
throw
new
IllegalArgumentException
(
"初始化OptionalSqlSessionTemplate错误!请设置spring.muti-datasource.data-source-name属性的值!"
);
}
Map
<
Object
,
SqlSessionFactory
>
sqlSessionFactoryMap
=
new
HashMap
<>();
sqlSessionFactoryMap
.
put
(
druidProperties
.
getDataSourceName
(),
sqlSessionFactoryPrimary
);
sqlSessionFactoryMap
.
put
(
mutiDataSourceProperties
.
getDataSourceName
(),
sqlSessionFactoryBusiness
);
return
new
OptionalSqlSessionTemplate
(
sqlSessionFactoryPrimary
,
sqlSessionFactoryMap
);
}
/**
* mybatis-plus分页插件
*/
@Bean
public
PaginationInterceptor
paginationInterceptor
()
{
return
new
PaginationInterceptor
();
}
/**
* 数据范围mybatis插件
*/
@Bean
public
DataScopeInterceptor
dataScopeInterceptor
()
{
return
new
DataScopeInterceptor
();
}
/**
* 乐观锁mybatis插件
*/
@Bean
public
OptimisticLockerInterceptor
optimisticLockerInterceptor
()
{
return
new
OptimisticLockerInterceptor
();
}
/**
* 创建数据源
*/
private
SqlSessionFactory
createSqlSessionFactory
(
DataSource
dataSource
)
{
try
{
MybatisSqlSessionFactoryBean
bean
=
new
MybatisSqlSessionFactoryBean
();
bean
.
setDataSource
(
dataSource
);
bean
.
setMapperLocations
(
new
PathMatchingResourcePatternResolver
().
getResources
(
MAPPING_XML_CLASSPATH
));
bean
.
setVfs
(
SpringBootVFS
.
class
);
bean
.
setPlugins
(
new
Interceptor
[]{
paginationInterceptor
(),
dataScopeInterceptor
(),
optimisticLockerInterceptor
()
});
return
bean
.
getObject
();
}
catch
(
Exception
e
)
{
log
.
error
(
"初始化SqlSessionFactory错误!"
,
e
);
throw
new
ServiceException
(
500
,
"初始化SqlSessionFactory错误!"
);
}
}
}
src/main/resources/application-dev.yml
View file @
997656eb
spring
:
datasource
:
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://127.0.0.1:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
username
:
root
password
:
root
filters
:
wall,mergeStat
data-source-name
:
gunsdb
#多数据源情况的配置
guns
:
muti-datasource
:
open
:
false
url
:
jdbc:mysql://127.0.0.1:3306/guns_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://127.0.0.1:3306/guns_test_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
username
:
root
password
:
root
dataSourceNames
:
-
dataSourceGuns
-
dataSourceBiz
\ No newline at end of file
data-source-name
:
otherdb
src/main/resources/application-local.yml
View file @
997656eb
spring
:
datasource
:
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://127.0.0.1:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
username
:
root
password
:
root
filters
:
wall,mergeStat
data-source-name
:
gunsdb
#多数据源情况的配置
guns
:
muti-datasource
:
open
:
false
url
:
jdbc:mysql://127.0.0.1:3306/guns_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://127.0.0.1:3306/guns_test_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT
username
:
root
password
:
root
dataSourceNames
:
-
dataSourceGuns
-
dataSourceBiz
\ No newline at end of file
data-source-name
:
otherdb
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment