style(all): 使用IDEA默认的格式化方案
This commit is contained in:
parent
07a5419a5c
commit
89a4ffae18
@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@SpringBootApplication
|
||||
public class LoadApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoadApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoadApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -13,13 +13,13 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
@EnableSwagger2
|
||||
public class SwaggerAutoConfig {
|
||||
|
||||
@Bean
|
||||
public Docket api() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(ApiInfo.DEFAULT)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.baomidou.samples.dynamicload.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
@Bean
|
||||
public Docket api() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(ApiInfo.DEFAULT)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.baomidou.samples.dynamicload.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
}
|
@ -1,26 +1,18 @@
|
||||
package com.baomidou.samples.dynamicload.controller;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.JndiDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.*;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.samples.dynamicload.dto.DataSourceDTO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.Set;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Set;
|
||||
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@ -28,78 +20,78 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@Api(tags = "添加删除数据源")
|
||||
public class LoadController {
|
||||
|
||||
private final DataSource dataSource;
|
||||
private final DataSourceCreator dataSourceCreator;
|
||||
private final BasicDataSourceCreator basicDataSourceCreator;
|
||||
private final JndiDataSourceCreator jndiDataSourceCreator;
|
||||
private final DruidDataSourceCreator druidDataSourceCreator;
|
||||
private final HikariDataSourceCreator hikariDataSourceCreator;
|
||||
private final DataSource dataSource;
|
||||
private final DataSourceCreator dataSourceCreator;
|
||||
private final BasicDataSourceCreator basicDataSourceCreator;
|
||||
private final JndiDataSourceCreator jndiDataSourceCreator;
|
||||
private final DruidDataSourceCreator druidDataSourceCreator;
|
||||
private final HikariDataSourceCreator hikariDataSourceCreator;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("获取当前所有数据源")
|
||||
public Set<String> now() {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@GetMapping
|
||||
@ApiOperation("获取当前所有数据源")
|
||||
public Set<String> now() {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@ApiOperation("通用添加数据源(推荐)")
|
||||
public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@PostMapping("/add")
|
||||
@ApiOperation("通用添加数据源(推荐)")
|
||||
public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@PostMapping("/addBasic")
|
||||
@ApiOperation(value = "添加基础数据源", notes = "调用Springboot内置方法创建数据源,兼容1,2")
|
||||
public Set<String> addBasic(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = basicDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@PostMapping("/addBasic")
|
||||
@ApiOperation(value = "添加基础数据源", notes = "调用Springboot内置方法创建数据源,兼容1,2")
|
||||
public Set<String> addBasic(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = basicDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@PostMapping("/addJndi")
|
||||
@ApiOperation("添加JNDI数据源")
|
||||
public Set<String> addJndi(String pollName, String jndiName) {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = jndiDataSourceCreator.createDataSource(jndiName);
|
||||
ds.addDataSource(pollName, dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@PostMapping("/addJndi")
|
||||
@ApiOperation("添加JNDI数据源")
|
||||
public Set<String> addJndi(String pollName, String jndiName) {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = jndiDataSourceCreator.createDataSource(jndiName);
|
||||
ds.addDataSource(pollName, dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@PostMapping("/addDruid")
|
||||
@ApiOperation("基础Druid数据源")
|
||||
public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@PostMapping("/addDruid")
|
||||
@ApiOperation("基础Druid数据源")
|
||||
public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@PostMapping("/addHikariCP")
|
||||
@ApiOperation("基础HikariCP数据源")
|
||||
public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
@PostMapping("/addHikariCP")
|
||||
@ApiOperation("基础HikariCP数据源")
|
||||
public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
|
||||
DataSourceProperty dataSourceProperty = new DataSourceProperty();
|
||||
BeanUtils.copyProperties(dto, dataSourceProperty);
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
ds.addDataSource(dto.getPollName(), dataSource);
|
||||
return ds.getCurrentDataSources().keySet();
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@ApiOperation("删除数据源")
|
||||
public String remove(String name) {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
ds.removeDataSource(name);
|
||||
return "删除成功";
|
||||
}
|
||||
@DeleteMapping
|
||||
@ApiOperation("删除数据源")
|
||||
public String remove(String name) {
|
||||
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
|
||||
ds.removeDataSource(name);
|
||||
return "删除成功";
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.baomidou.samples.dynamicload.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @date 2020/1/27
|
||||
@ -11,23 +12,23 @@ import lombok.Data;
|
||||
@Data
|
||||
public class DataSourceDTO {
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "连接池名称", example = "test")
|
||||
private String pollName;
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "连接池名称", example = "test")
|
||||
private String pollName;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC driver", example = "org.h2.Driver")
|
||||
private String driverClassName;
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC driver", example = "org.h2.Driver")
|
||||
private String driverClassName;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC url 地址", example = "jdbc:h2:mem:test10")
|
||||
private String url;
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC url 地址", example = "jdbc:h2:mem:test10")
|
||||
private String url;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC 用户名", example = "sa")
|
||||
private String username;
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "JDBC 用户名", example = "sa")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "JDBC 密码")
|
||||
private String password;
|
||||
@ApiModelProperty(value = "JDBC 密码")
|
||||
private String password;
|
||||
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.druid.mybatis.mapper")
|
||||
public class DruidMybatisApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DruidMybatisApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DruidMybatisApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -2,33 +2,33 @@ package com.baomidou.samples.druid.mybatis.entity;
|
||||
|
||||
public class User {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package com.baomidou.samples.druid.mybatis.mapper;
|
||||
|
||||
import com.baomidou.samples.druid.mybatis.entity.User;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserMapper {
|
||||
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
|
||||
@Select("SELECT * FROM user where age > #{age}")
|
||||
List<User> selectUsers(@Param("age") Integer age);
|
||||
@Select("SELECT * FROM user where age > #{age}")
|
||||
List<User> selectUsers(@Param("age") Integer age);
|
||||
}
|
||||
|
@ -2,13 +2,14 @@ package com.baomidou.samples.druid.mybatis.service;
|
||||
|
||||
|
||||
import com.baomidou.samples.druid.mybatis.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
void addUser(User user);
|
||||
void addUser(User user);
|
||||
|
||||
List selectUsersFromDs();
|
||||
List selectUsersFromDs();
|
||||
|
||||
List selectUserFromDsGroup();
|
||||
List selectUserFromDsGroup();
|
||||
}
|
||||
|
@ -5,30 +5,31 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.samples.druid.mybatis.entity.User;
|
||||
import com.baomidou.samples.druid.mybatis.mapper.UserMapper;
|
||||
import com.baomidou.samples.druid.mybatis.service.UserService;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
userMapper.addUser(user.getName(), user.getAge());
|
||||
}
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
userMapper.addUser(user.getName(), user.getAge());
|
||||
}
|
||||
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return userMapper.selectUsers(1);
|
||||
}
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return userMapper.selectUsers(1);
|
||||
}
|
||||
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return userMapper.selectUsers(1);
|
||||
}
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return userMapper.selectUsers(1);
|
||||
}
|
||||
}
|
||||
|
@ -3,38 +3,39 @@ package com.baomidou.samples.druid.mybatis.test;
|
||||
import com.baomidou.samples.druid.mybatis.DruidMybatisApplication;
|
||||
import com.baomidou.samples.druid.mybatis.entity.User;
|
||||
import com.baomidou.samples.druid.mybatis.service.UserService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = DruidMybatisApplication.class)
|
||||
public class DruidMybatisApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,22 @@
|
||||
package com.baomidou.samples.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
|
||||
return new JdbcTemplate(dataSource);
|
||||
}
|
||||
@Bean
|
||||
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
|
||||
return new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
}
|
@ -2,33 +2,33 @@ package com.baomidou.samples.jdbc.entity;
|
||||
|
||||
public class User {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
package com.baomidou.samples.jdbc.service;
|
||||
|
||||
import com.baomidou.samples.jdbc.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
void addUser(User user);
|
||||
void addUser(User user);
|
||||
|
||||
List selectUsersFromDs();
|
||||
List selectUsersFromDs();
|
||||
|
||||
List selectUserFromDsGroup();
|
||||
List selectUserFromDsGroup();
|
||||
}
|
||||
|
@ -4,32 +4,33 @@ package com.baomidou.samples.jdbc.service.impl;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.samples.jdbc.entity.User;
|
||||
import com.baomidou.samples.jdbc.service.UserService;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
jdbcTemplate.update("INSERT INTO user (name,age) VALUES(?, ?)",
|
||||
new Object[]{user.getName(), user.getAge()});
|
||||
}
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
jdbcTemplate.update("INSERT INTO user (name,age) VALUES(?, ?)",
|
||||
new Object[]{user.getName(), user.getAge()});
|
||||
}
|
||||
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return jdbcTemplate.queryForList("SELECT * FROM user");
|
||||
}
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return jdbcTemplate.queryForList("SELECT * FROM user");
|
||||
}
|
||||
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return jdbcTemplate.queryForList("SELECT * FROM user");
|
||||
}
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return jdbcTemplate.queryForList("SELECT * FROM user");
|
||||
}
|
||||
}
|
||||
|
@ -3,37 +3,38 @@ package com.baomidou.samples.jdbc.test;
|
||||
import com.baomidou.samples.jdbc.Application;
|
||||
import com.baomidou.samples.jdbc.entity.User;
|
||||
import com.baomidou.samples.jdbc.service.UserService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class ApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.mybatis.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -2,33 +2,33 @@ package com.baomidou.samples.mybatis.entity;
|
||||
|
||||
public class User {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package com.baomidou.samples.mybatis.mapper;
|
||||
|
||||
import com.baomidou.samples.mybatis.entity.User;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//@DS("slave")这里可以使用但不建议,不要和service同时使用
|
||||
public interface UserMapper {
|
||||
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
|
||||
@Select("SELECT * FROM user")
|
||||
List<User> selectUsers();
|
||||
@Select("SELECT * FROM user")
|
||||
List<User> selectUsers();
|
||||
}
|
||||
|
@ -2,13 +2,14 @@ package com.baomidou.samples.mybatis.service;
|
||||
|
||||
|
||||
import com.baomidou.samples.mybatis.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
void addUser(User user);
|
||||
void addUser(User user);
|
||||
|
||||
List selectUsersFromDs();
|
||||
List selectUsersFromDs();
|
||||
|
||||
List selectUserFromDsGroup();
|
||||
List selectUserFromDsGroup();
|
||||
}
|
||||
|
@ -5,30 +5,31 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.samples.mybatis.entity.User;
|
||||
import com.baomidou.samples.mybatis.mapper.UserMapper;
|
||||
import com.baomidou.samples.mybatis.service.UserService;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
userMapper.addUser(user.getName(), user.getAge());
|
||||
}
|
||||
@Override
|
||||
public void addUser(User user) {
|
||||
userMapper.addUser(user.getName(), user.getAge());
|
||||
}
|
||||
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@DS("slave_1")
|
||||
@Override
|
||||
public List selectUsersFromDs() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@DS("slave")
|
||||
@Override
|
||||
public List selectUserFromDsGroup() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
}
|
||||
|
@ -4,37 +4,38 @@ package com.baomidou.samples.mybatis.test;
|
||||
import com.baomidou.samples.mybatis.Application;
|
||||
import com.baomidou.samples.mybatis.entity.User;
|
||||
import com.baomidou.samples.mybatis.service.UserService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class ApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
@Test
|
||||
public void addUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
@Test
|
||||
public void selectUsersFromDs() {
|
||||
userService.selectUsersFromDs();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
@Test
|
||||
public void selectUserFromDsGroup() {
|
||||
userService.selectUserFromDsGroup();
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.mybatisplus2.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -5,34 +5,34 @@ import com.baomidou.mybatisplus.enums.IdType;
|
||||
|
||||
public class User {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,6 @@ import com.baomidou.samples.mybatisplus2.entity.User;
|
||||
|
||||
public interface UserService extends IService<User> {
|
||||
|
||||
void addUser(User user);
|
||||
void addUser(User user);
|
||||
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ import org.springframework.stereotype.Service;
|
||||
@DS("slave")
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
@Override
|
||||
@Override
|
||||
// @DS("master")//这里必须包一层,不能调用mp默认的插入,因为会走到从库去
|
||||
public void addUser(User user) {
|
||||
baseMapper.insert(user);
|
||||
}
|
||||
public void addUser(User user) {
|
||||
baseMapper.insert(user);
|
||||
}
|
||||
}
|
||||
|
@ -3,33 +3,34 @@ package com.baomidou.samples.mybatisplus2.test;
|
||||
import com.baomidou.samples.mybatisplus2.Application;
|
||||
import com.baomidou.samples.mybatisplus2.entity.User;
|
||||
import com.baomidou.samples.mybatisplus2.service.UserService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class ApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
public void testAddUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
@Test
|
||||
public void testAddUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectUser() {
|
||||
userService.selectList(null);
|
||||
}
|
||||
@Test
|
||||
public void testSelectUser() {
|
||||
userService.selectList(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.mybatisplus.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -5,34 +5,34 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
|
||||
public class User {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,6 @@ import com.baomidou.samples.mybatisplus.entity.User;
|
||||
|
||||
public interface UserService extends IService<User> {
|
||||
|
||||
void addUser(User user);
|
||||
void addUser(User user);
|
||||
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ import org.springframework.stereotype.Service;
|
||||
@DS("slave")
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
@Override
|
||||
@DS("master")//这里必须包一层,不能调用mp默认的插入,因为会走到从库去
|
||||
public void addUser(User user) {
|
||||
baseMapper.insert(user);
|
||||
}
|
||||
@Override
|
||||
@DS("master")//这里必须包一层,不能调用mp默认的插入,因为会走到从库去
|
||||
public void addUser(User user) {
|
||||
baseMapper.insert(user);
|
||||
}
|
||||
}
|
||||
|
@ -3,32 +3,33 @@ package com.baomidou.samples.mybatisplus3.test;
|
||||
import com.baomidou.samples.mybatisplus.Application;
|
||||
import com.baomidou.samples.mybatisplus.entity.User;
|
||||
import com.baomidou.samples.mybatisplus.service.UserService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class ApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
public void testAddUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
@Test
|
||||
public void testAddUser() {
|
||||
User user = new User();
|
||||
user.setName("测试用户" + random.nextInt());
|
||||
user.setAge(random.nextInt(100));
|
||||
userService.addUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectUser() {
|
||||
userService.list(null);
|
||||
}
|
||||
@Test
|
||||
public void testSelectUser() {
|
||||
userService.list(null);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.nest.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +1,39 @@
|
||||
package com.baomidou.samples.nest;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@Component
|
||||
public class CreateDatabaseOnStarted implements ApplicationListener<ApplicationStartedEvent> {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||
try {
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS teacher (\n" +
|
||||
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
|
||||
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
|
||||
" age INT(11) NULL DEFAULT NULL ,\n" +
|
||||
" PRIMARY KEY (id)\n" +
|
||||
");");
|
||||
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS student (\n" +
|
||||
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
|
||||
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
|
||||
" age INT(11) NULL DEFAULT NULL ,\n" +
|
||||
" PRIMARY KEY (id)\n" +
|
||||
");");
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||
try {
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS teacher (\n" +
|
||||
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
|
||||
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
|
||||
" age INT(11) NULL DEFAULT NULL ,\n" +
|
||||
" PRIMARY KEY (id)\n" +
|
||||
");");
|
||||
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS student (\n" +
|
||||
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
|
||||
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
|
||||
" age INT(11) NULL DEFAULT NULL ,\n" +
|
||||
" PRIMARY KEY (id)\n" +
|
||||
");");
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,27 +9,27 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
|
||||
@Autowired
|
||||
private SchoolService schoolService;
|
||||
@Autowired
|
||||
private SchoolService schoolService;
|
||||
|
||||
@GetMapping("/tx1")
|
||||
public void tx1() {
|
||||
//外层不加事物,里面每个单独加事物(支持,不过感觉没毛用)
|
||||
schoolService.addTeacherAndStudent();
|
||||
}
|
||||
@GetMapping("/tx1")
|
||||
public void tx1() {
|
||||
//外层不加事物,里面每个单独加事物(支持,不过感觉没毛用)
|
||||
schoolService.addTeacherAndStudent();
|
||||
}
|
||||
|
||||
@GetMapping("/tx2")
|
||||
public void tx2() {
|
||||
//外层加事物,里面每个也加事物(不支持!!)其实只要加了事物就不支持多库
|
||||
schoolService.addTeacherAndStudentWithTx();
|
||||
}
|
||||
@GetMapping("/tx2")
|
||||
public void tx2() {
|
||||
//外层加事物,里面每个也加事物(不支持!!)其实只要加了事物就不支持多库
|
||||
schoolService.addTeacherAndStudentWithTx();
|
||||
}
|
||||
|
||||
@GetMapping("/tx3")
|
||||
public void tx3() {
|
||||
//单独调用加事物单库(支持)
|
||||
teacherService.addTeacherWithTx("tt", 12);
|
||||
}
|
||||
@GetMapping("/tx3")
|
||||
public void tx3() {
|
||||
//单独调用加事物单库(支持)
|
||||
teacherService.addTeacherWithTx("tt", 12);
|
||||
}
|
||||
}
|
||||
|
@ -2,33 +2,33 @@ package com.baomidou.samples.nest.entiry;
|
||||
|
||||
public class Student {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -2,33 +2,33 @@ package com.baomidou.samples.nest.entiry;
|
||||
|
||||
public class Teacher {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package com.baomidou.samples.nest.mapper;
|
||||
|
||||
import com.baomidou.samples.nest.entiry.Student;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StudentMapper {
|
||||
|
||||
@Insert("INSERT INTO student (name,age) values (#{name},#{age})")
|
||||
boolean addStudent(@Param("name") String name, @Param("age") Integer age);
|
||||
@Insert("INSERT INTO student (name,age) values (#{name},#{age})")
|
||||
boolean addStudent(@Param("name") String name, @Param("age") Integer age);
|
||||
|
||||
@Select("SELECT * FROM student")
|
||||
List<Student> selectStudents();
|
||||
@Select("SELECT * FROM student")
|
||||
List<Student> selectStudents();
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package com.baomidou.samples.nest.mapper;
|
||||
|
||||
import com.baomidou.samples.nest.entiry.Teacher;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TeacherMapper {
|
||||
|
||||
@Insert("INSERT INTO teacher (name,age) values (#{name},#{age})")
|
||||
boolean addTeacher(@Param("name") String name, @Param("age") Integer age);
|
||||
@Insert("INSERT INTO teacher (name,age) values (#{name},#{age})")
|
||||
boolean addTeacher(@Param("name") String name, @Param("age") Integer age);
|
||||
|
||||
@Select("SELECT * FROM teacher")
|
||||
List<Teacher> selectTeachers();
|
||||
@Select("SELECT * FROM teacher")
|
||||
List<Teacher> selectTeachers();
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ package com.baomidou.samples.nest.service;
|
||||
|
||||
public interface SchoolService {
|
||||
|
||||
void selectTeachersAndStudents();
|
||||
void selectTeachersAndStudents();
|
||||
|
||||
void selectTeachersInnerStudents();
|
||||
void selectTeachersInnerStudents();
|
||||
|
||||
void addTeacherAndStudent();
|
||||
void addTeacherAndStudent();
|
||||
|
||||
void addTeacherAndStudentWithTx();
|
||||
void addTeacherAndStudentWithTx();
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
package com.baomidou.samples.nest.service;
|
||||
|
||||
import com.baomidou.samples.nest.entiry.Student;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StudentService {
|
||||
|
||||
boolean addStudentWithTx(String name, Integer age);
|
||||
boolean addStudentWithTx(String name, Integer age);
|
||||
|
||||
boolean addStudentNoTx(String name, Integer age);
|
||||
boolean addStudentNoTx(String name, Integer age);
|
||||
|
||||
|
||||
List<Student> selectStudents();
|
||||
List<Student> selectStudents();
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package com.baomidou.samples.nest.service;
|
||||
|
||||
import com.baomidou.samples.nest.entiry.Teacher;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface TeacherService {
|
||||
|
||||
boolean addTeacherWithTx(String name, Integer age);
|
||||
boolean addTeacherWithTx(String name, Integer age);
|
||||
|
||||
boolean addTeacherNoTx(String name, Integer age);
|
||||
boolean addTeacherNoTx(String name, Integer age);
|
||||
|
||||
|
||||
List<Teacher> selectTeachers();
|
||||
List<Teacher> selectTeachers();
|
||||
|
||||
void selectTeachersInnerStudents();
|
||||
void selectTeachersInnerStudents();
|
||||
}
|
||||
|
@ -10,33 +10,33 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Service
|
||||
public class SchoolServiceImpl implements SchoolService {
|
||||
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
|
||||
@Override
|
||||
public void selectTeachersAndStudents() {
|
||||
teacherService.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
@Override
|
||||
public void selectTeachersAndStudents() {
|
||||
teacherService.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTeachersInnerStudents() {
|
||||
teacherService.selectTeachersInnerStudents();
|
||||
}
|
||||
@Override
|
||||
public void selectTeachersInnerStudents() {
|
||||
teacherService.selectTeachersInnerStudents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTeacherAndStudent() {
|
||||
teacherService.addTeacherWithTx("ss", 1);
|
||||
studentService.addStudentWithTx("tt", 2);
|
||||
}
|
||||
@Override
|
||||
public void addTeacherAndStudent() {
|
||||
teacherService.addTeacherWithTx("ss", 1);
|
||||
studentService.addStudentWithTx("tt", 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addTeacherAndStudentWithTx() {
|
||||
teacherService.addTeacherWithTx("ss", 1);
|
||||
studentService.addStudentWithTx("tt", 2);
|
||||
}
|
||||
@Override
|
||||
@Transactional
|
||||
public void addTeacherAndStudentWithTx() {
|
||||
teacherService.addTeacherWithTx("ss", 1);
|
||||
studentService.addStudentWithTx("tt", 2);
|
||||
}
|
||||
}
|
||||
|
@ -4,31 +4,32 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.samples.nest.entiry.Student;
|
||||
import com.baomidou.samples.nest.mapper.StudentMapper;
|
||||
import com.baomidou.samples.nest.service.StudentService;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("student")
|
||||
public class StudentServiceImpl implements StudentService {
|
||||
|
||||
@Resource
|
||||
private StudentMapper studentMapper;
|
||||
@Resource
|
||||
private StudentMapper studentMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean addStudentWithTx(String name, Integer age) {
|
||||
return studentMapper.addStudent(name, age);
|
||||
}
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean addStudentWithTx(String name, Integer age) {
|
||||
return studentMapper.addStudent(name, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addStudentNoTx(String name, Integer age) {
|
||||
return studentMapper.addStudent(name, age);
|
||||
}
|
||||
@Override
|
||||
public boolean addStudentNoTx(String name, Integer age) {
|
||||
return studentMapper.addStudent(name, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Student> selectStudents() {
|
||||
return studentMapper.selectStudents();
|
||||
}
|
||||
@Override
|
||||
public List<Student> selectStudents() {
|
||||
return studentMapper.selectStudents();
|
||||
}
|
||||
}
|
||||
|
@ -5,40 +5,41 @@ import com.baomidou.samples.nest.entiry.Teacher;
|
||||
import com.baomidou.samples.nest.mapper.TeacherMapper;
|
||||
import com.baomidou.samples.nest.service.StudentService;
|
||||
import com.baomidou.samples.nest.service.TeacherService;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("teacher")
|
||||
public class TeacherServiceImpl implements TeacherService {
|
||||
|
||||
@Resource
|
||||
private TeacherMapper teacherMapper;
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
@Resource
|
||||
private TeacherMapper teacherMapper;
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean addTeacherWithTx(String name, Integer age) {
|
||||
return teacherMapper.addTeacher(name, age);
|
||||
}
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean addTeacherWithTx(String name, Integer age) {
|
||||
return teacherMapper.addTeacher(name, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addTeacherNoTx(String name, Integer age) {
|
||||
return teacherMapper.addTeacher(name, age);
|
||||
}
|
||||
@Override
|
||||
public boolean addTeacherNoTx(String name, Integer age) {
|
||||
return teacherMapper.addTeacher(name, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Teacher> selectTeachers() {
|
||||
return teacherMapper.selectTeachers();
|
||||
}
|
||||
@Override
|
||||
public List<Teacher> selectTeachers() {
|
||||
return teacherMapper.selectTeachers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTeachersInnerStudents() {
|
||||
teacherMapper.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
@Override
|
||||
public void selectTeachersInnerStudents() {
|
||||
teacherMapper.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
}
|
||||
|
@ -5,46 +5,47 @@ import com.baomidou.samples.nest.Application;
|
||||
import com.baomidou.samples.nest.service.SchoolService;
|
||||
import com.baomidou.samples.nest.service.StudentService;
|
||||
import com.baomidou.samples.nest.service.TeacherService;
|
||||
import java.util.Random;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
|
||||
public class ApplicationTest {
|
||||
|
||||
private Random random = new Random();
|
||||
private Random random = new Random();
|
||||
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
@Autowired
|
||||
private SchoolService schoolService;
|
||||
@Autowired
|
||||
private TeacherService teacherService;
|
||||
@Autowired
|
||||
private StudentService studentService;
|
||||
@Autowired
|
||||
private SchoolService schoolService;
|
||||
|
||||
@Test
|
||||
public void nest1() {
|
||||
//直接在controller
|
||||
teacherService.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
@Test
|
||||
public void nest1() {
|
||||
//直接在controller
|
||||
teacherService.selectTeachers();
|
||||
studentService.selectStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nest2() {
|
||||
schoolService.selectTeachersAndStudents();
|
||||
}
|
||||
@Test
|
||||
public void nest2() {
|
||||
schoolService.selectTeachersAndStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nest3() {
|
||||
schoolService.selectTeachersInnerStudents();
|
||||
}
|
||||
@Test
|
||||
public void nest3() {
|
||||
schoolService.selectTeachersInnerStudents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tx() {
|
||||
teacherService.selectTeachers();
|
||||
}
|
||||
@Test
|
||||
public void tx() {
|
||||
teacherService.selectTeachers();
|
||||
}
|
||||
}
|
@ -9,8 +9,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.seata.dao")
|
||||
public class SeataApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SeataApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SeataApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,16 @@ package com.baomidou.samples.seata.common;
|
||||
* 订单状态
|
||||
*/
|
||||
public enum OrderStatus {
|
||||
/**
|
||||
* INIT
|
||||
*/
|
||||
INIT,
|
||||
/**
|
||||
* SUCCESS
|
||||
*/
|
||||
SUCCESS,
|
||||
/**
|
||||
* FAIL
|
||||
*/
|
||||
FAIL
|
||||
/**
|
||||
* INIT
|
||||
*/
|
||||
INIT,
|
||||
/**
|
||||
* SUCCESS
|
||||
*/
|
||||
SUCCESS,
|
||||
/**
|
||||
* FAIL
|
||||
*/
|
||||
FAIL
|
||||
}
|
@ -15,12 +15,12 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@Slf4j
|
||||
public class OrderController {
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@PostMapping("/placeOrder")
|
||||
public String placeOrder(@Validated @RequestBody PlaceOrderRequest request) {
|
||||
orderService.placeOrder(request);
|
||||
return "下单成功";
|
||||
}
|
||||
@PostMapping("/placeOrder")
|
||||
public String placeOrder(@Validated @RequestBody PlaceOrderRequest request) {
|
||||
orderService.placeOrder(request);
|
||||
return "下单成功";
|
||||
}
|
||||
}
|
@ -1,23 +1,24 @@
|
||||
package com.baomidou.samples.seata.dto;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PlaceOrderRequest {
|
||||
|
||||
@NotNull
|
||||
private Long userId;
|
||||
@NotNull
|
||||
private Long userId;
|
||||
|
||||
@NotNull
|
||||
private Long productId;
|
||||
@NotNull
|
||||
private Long productId;
|
||||
|
||||
@NotNull
|
||||
private Integer amount;
|
||||
@NotNull
|
||||
private Integer amount;
|
||||
}
|
@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class ReduceBalanceRequest {
|
||||
|
||||
private Long userId;
|
||||
private Long userId;
|
||||
|
||||
private Integer price;
|
||||
private Integer price;
|
||||
}
|
@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class ReduceStockRequest {
|
||||
|
||||
private Long productId;
|
||||
private Long productId;
|
||||
|
||||
private Integer amount;
|
||||
private Integer amount;
|
||||
}
|
@ -2,21 +2,22 @@ package com.baomidou.samples.seata.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.util.Date;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class Account {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 余额
|
||||
*/
|
||||
private Double balance;
|
||||
/**
|
||||
* 余额
|
||||
*/
|
||||
private Double balance;
|
||||
|
||||
private Date lastUpdateTime;
|
||||
private Date lastUpdateTime;
|
||||
}
|
@ -12,27 +12,27 @@ import lombok.Data;
|
||||
@TableName("p_order")
|
||||
public class Order {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
private Long productId;
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private OrderStatus status;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer amount;
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private Double totalPrice;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 商品ID
|
||||
*/
|
||||
private Long productId;
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private OrderStatus status;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer amount;
|
||||
/**
|
||||
* 总金额
|
||||
*/
|
||||
private Double totalPrice;
|
||||
}
|
@ -2,24 +2,25 @@ package com.baomidou.samples.seata.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.util.Date;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class Product {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private Double price;
|
||||
/**
|
||||
* 库存
|
||||
*/
|
||||
private Integer stock;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private Double price;
|
||||
/**
|
||||
* 库存
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
private Date lastUpdateTime;
|
||||
private Date lastUpdateTime;
|
||||
}
|
@ -2,10 +2,10 @@ package com.baomidou.samples.seata.service;
|
||||
|
||||
public interface AccountService {
|
||||
|
||||
/**
|
||||
* @param userId 用户 ID
|
||||
* @param price 扣减金额
|
||||
*/
|
||||
void reduceBalance(Long userId, Double price);
|
||||
/**
|
||||
* @param userId 用户 ID
|
||||
* @param price 扣减金额
|
||||
*/
|
||||
void reduceBalance(Long userId, Double price);
|
||||
|
||||
}
|
@ -4,10 +4,10 @@ import com.baomidou.samples.seata.dto.PlaceOrderRequest;
|
||||
|
||||
public interface OrderService {
|
||||
|
||||
/**
|
||||
* 下单
|
||||
*
|
||||
* @param placeOrderRequest 订单请求参数
|
||||
*/
|
||||
void placeOrder(PlaceOrderRequest placeOrderRequest);
|
||||
/**
|
||||
* 下单
|
||||
*
|
||||
* @param placeOrderRequest 订单请求参数
|
||||
*/
|
||||
void placeOrder(PlaceOrderRequest placeOrderRequest);
|
||||
}
|
@ -2,12 +2,12 @@ package com.baomidou.samples.seata.service;
|
||||
|
||||
public interface ProductService {
|
||||
|
||||
/**
|
||||
* 扣减库存
|
||||
*
|
||||
* @param productId 商品 ID
|
||||
* @param amount 扣减数量
|
||||
* @return 商品总价
|
||||
*/
|
||||
Double reduceStock(Long productId, Integer amount);
|
||||
/**
|
||||
* 扣减库存
|
||||
*
|
||||
* @param productId 商品 ID
|
||||
* @param amount 扣减数量
|
||||
* @return 商品总价
|
||||
*/
|
||||
Double reduceStock(Long productId, Integer amount);
|
||||
}
|
@ -5,43 +5,44 @@ import com.baomidou.samples.seata.dao.AccountDao;
|
||||
import com.baomidou.samples.seata.entity.Account;
|
||||
import com.baomidou.samples.seata.service.AccountService;
|
||||
import io.seata.core.context.RootContext;
|
||||
import javax.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AccountServiceImpl implements AccountService {
|
||||
|
||||
@Resource
|
||||
private AccountDao accountDao;
|
||||
@Resource
|
||||
private AccountDao accountDao;
|
||||
|
||||
/**
|
||||
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
|
||||
*/
|
||||
@DS("account")
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void reduceBalance(Long userId, Double price) {
|
||||
log.info("=============ACCOUNT START=================");
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
/**
|
||||
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
|
||||
*/
|
||||
@DS("account")
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void reduceBalance(Long userId, Double price) {
|
||||
log.info("=============ACCOUNT START=================");
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
|
||||
Account account = accountDao.selectById(userId);
|
||||
Double balance = account.getBalance();
|
||||
log.info("下单用户{}余额为 {},商品总价为{}", userId, balance, price);
|
||||
Account account = accountDao.selectById(userId);
|
||||
Double balance = account.getBalance();
|
||||
log.info("下单用户{}余额为 {},商品总价为{}", userId, balance, price);
|
||||
|
||||
if (balance < price) {
|
||||
log.warn("用户 {} 余额不足,当前余额:{}", userId, balance);
|
||||
throw new RuntimeException("余额不足");
|
||||
if (balance < price) {
|
||||
log.warn("用户 {} 余额不足,当前余额:{}", userId, balance);
|
||||
throw new RuntimeException("余额不足");
|
||||
}
|
||||
log.info("开始扣减用户 {} 余额", userId);
|
||||
double currentBalance = account.getBalance() - price;
|
||||
account.setBalance(currentBalance);
|
||||
accountDao.updateById(account);
|
||||
log.info("扣减用户 {} 余额成功,扣减后用户账户余额为{}", userId, currentBalance);
|
||||
log.info("=============ACCOUNT END=================");
|
||||
}
|
||||
log.info("开始扣减用户 {} 余额", userId);
|
||||
double currentBalance = account.getBalance() - price;
|
||||
account.setBalance(currentBalance);
|
||||
accountDao.updateById(account);
|
||||
log.info("扣减用户 {} 余额成功,扣减后用户账户余额为{}", userId, currentBalance);
|
||||
log.info("=============ACCOUNT END=================");
|
||||
}
|
||||
|
||||
}
|
@ -10,54 +10,55 @@ import com.baomidou.samples.seata.service.OrderService;
|
||||
import com.baomidou.samples.seata.service.ProductService;
|
||||
import io.seata.core.context.RootContext;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
import javax.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
|
||||
@Resource
|
||||
private OrderDao orderDao;
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
@Autowired
|
||||
private ProductService productService;
|
||||
@Resource
|
||||
private OrderDao orderDao;
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
@Autowired
|
||||
private ProductService productService;
|
||||
|
||||
@DS("order")
|
||||
@Override
|
||||
@Transactional
|
||||
@GlobalTransactional
|
||||
public void placeOrder(PlaceOrderRequest request) {
|
||||
log.info("=============ORDER START=================");
|
||||
Long userId = request.getUserId();
|
||||
Long productId = request.getProductId();
|
||||
Integer amount = request.getAmount();
|
||||
log.info("收到下单请求,用户:{}, 商品:{},数量:{}", userId, productId, amount);
|
||||
@DS("order")
|
||||
@Override
|
||||
@Transactional
|
||||
@GlobalTransactional
|
||||
public void placeOrder(PlaceOrderRequest request) {
|
||||
log.info("=============ORDER START=================");
|
||||
Long userId = request.getUserId();
|
||||
Long productId = request.getProductId();
|
||||
Integer amount = request.getAmount();
|
||||
log.info("收到下单请求,用户:{}, 商品:{},数量:{}", userId, productId, amount);
|
||||
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
|
||||
Order order = Order.builder()
|
||||
.userId(userId)
|
||||
.productId(productId)
|
||||
.status(OrderStatus.INIT)
|
||||
.amount(amount)
|
||||
.build();
|
||||
Order order = Order.builder()
|
||||
.userId(userId)
|
||||
.productId(productId)
|
||||
.status(OrderStatus.INIT)
|
||||
.amount(amount)
|
||||
.build();
|
||||
|
||||
orderDao.insert(order);
|
||||
log.info("订单一阶段生成,等待扣库存付款中");
|
||||
// 扣减库存并计算总价
|
||||
Double totalPrice = productService.reduceStock(productId, amount);
|
||||
// 扣减余额
|
||||
accountService.reduceBalance(userId, totalPrice);
|
||||
orderDao.insert(order);
|
||||
log.info("订单一阶段生成,等待扣库存付款中");
|
||||
// 扣减库存并计算总价
|
||||
Double totalPrice = productService.reduceStock(productId, amount);
|
||||
// 扣减余额
|
||||
accountService.reduceBalance(userId, totalPrice);
|
||||
|
||||
order.setStatus(OrderStatus.SUCCESS);
|
||||
order.setTotalPrice(totalPrice);
|
||||
orderDao.updateById(order);
|
||||
log.info("订单已成功下单");
|
||||
log.info("=============ORDER END=================");
|
||||
}
|
||||
order.setStatus(OrderStatus.SUCCESS);
|
||||
order.setTotalPrice(totalPrice);
|
||||
orderDao.updateById(order);
|
||||
log.info("订单已成功下单");
|
||||
log.info("=============ORDER END=================");
|
||||
}
|
||||
}
|
@ -5,46 +5,47 @@ import com.baomidou.samples.seata.dao.ProductDao;
|
||||
import com.baomidou.samples.seata.entity.Product;
|
||||
import com.baomidou.samples.seata.service.ProductService;
|
||||
import io.seata.core.context.RootContext;
|
||||
import javax.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ProductServiceImpl implements ProductService {
|
||||
|
||||
@Resource
|
||||
private ProductDao productDao;
|
||||
@Resource
|
||||
private ProductDao productDao;
|
||||
|
||||
/**
|
||||
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
|
||||
*/
|
||||
@DS("product")
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Override
|
||||
public Double reduceStock(Long productId, Integer amount) {
|
||||
log.info("=============PRODUCT START=================");
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
/**
|
||||
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
|
||||
*/
|
||||
@DS("product")
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Override
|
||||
public Double reduceStock(Long productId, Integer amount) {
|
||||
log.info("=============PRODUCT START=================");
|
||||
log.info("当前 XID: {}", RootContext.getXID());
|
||||
|
||||
// 检查库存
|
||||
Product product = productDao.selectById(productId);
|
||||
Integer stock = product.getStock();
|
||||
log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount);
|
||||
// 检查库存
|
||||
Product product = productDao.selectById(productId);
|
||||
Integer stock = product.getStock();
|
||||
log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount);
|
||||
|
||||
if (stock < amount) {
|
||||
log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock);
|
||||
throw new RuntimeException("库存不足");
|
||||
if (stock < amount) {
|
||||
log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock);
|
||||
throw new RuntimeException("库存不足");
|
||||
}
|
||||
log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice());
|
||||
// 扣减库存
|
||||
int currentStock = stock - amount;
|
||||
product.setStock(currentStock);
|
||||
productDao.updateById(product);
|
||||
double totalPrice = product.getPrice() * amount;
|
||||
log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice);
|
||||
log.info("=============PRODUCT END=================");
|
||||
return totalPrice;
|
||||
}
|
||||
log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice());
|
||||
// 扣减库存
|
||||
int currentStock = stock - amount;
|
||||
product.setStock(currentStock);
|
||||
productDao.updateById(product);
|
||||
double totalPrice = product.getPrice() * amount;
|
||||
log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice);
|
||||
log.info("=============PRODUCT END=================");
|
||||
return totalPrice;
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@MapperScan("com.baomidou.samples.spel.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -2,28 +2,29 @@ package com.baomidou.samples.spel.controller;
|
||||
|
||||
import com.baomidou.samples.spel.entity.User;
|
||||
import com.baomidou.samples.spel.service.UserService;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@GetMapping("/users")
|
||||
public List<User> usersFromSession(HttpServletRequest request) {
|
||||
request.getSession().setAttribute("tenantName", "tenant1");
|
||||
return userService.selectSpelBySession();
|
||||
}
|
||||
@GetMapping("/users")
|
||||
public List<User> usersFromSession(HttpServletRequest request) {
|
||||
request.getSession().setAttribute("tenantName", "tenant1");
|
||||
return userService.selectSpelBySession();
|
||||
}
|
||||
|
||||
@GetMapping("/users/header")
|
||||
public String usersFromHeader() {
|
||||
userService.selectSpelByHeader();
|
||||
return "success";
|
||||
}
|
||||
@GetMapping("/users/header")
|
||||
public String usersFromHeader() {
|
||||
userService.selectSpelByHeader();
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,43 +2,43 @@ package com.baomidou.samples.spel.entity;
|
||||
|
||||
public class User {
|
||||
|
||||
private Integer id;
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
private Integer age;
|
||||
private Integer age;
|
||||
|
||||
private String tenantName;
|
||||
private String tenantName;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
|
||||
public void setTenantName(String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
public void setTenantName(String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package com.baomidou.samples.spel.mapper;
|
||||
|
||||
import com.baomidou.samples.spel.entity.User;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//@DS("slave")这里可以使用但不建议,不要和service同时使用
|
||||
public interface UserMapper {
|
||||
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
|
||||
boolean addUser(@Param("name") String name, @Param("age") Integer age);
|
||||
|
||||
@Select("SELECT * FROM user")
|
||||
List<User> selectUsers();
|
||||
@Select("SELECT * FROM user")
|
||||
List<User> selectUsers();
|
||||
}
|
||||
|
@ -2,15 +2,16 @@ package com.baomidou.samples.spel.service;
|
||||
|
||||
|
||||
import com.baomidou.samples.spel.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
List selectSpelBySession();
|
||||
List selectSpelBySession();
|
||||
|
||||
List selectSpelByHeader();
|
||||
List selectSpelByHeader();
|
||||
|
||||
List selectSpelByKey(String tenantName);
|
||||
List selectSpelByKey(String tenantName);
|
||||
|
||||
List selecSpelByTenant(User user);
|
||||
List selecSpelByTenant(User user);
|
||||
}
|
||||
|
@ -5,38 +5,39 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.samples.spel.entity.User;
|
||||
import com.baomidou.samples.spel.mapper.UserMapper;
|
||||
import com.baomidou.samples.spel.service.UserService;
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("slave")
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
@DS("#session.tenantName")
|
||||
public List selectSpelBySession() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@Override
|
||||
@DS("#session.tenantName")
|
||||
public List selectSpelBySession() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DS("#header.tenantName")
|
||||
public List selectSpelByHeader() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@Override
|
||||
@DS("#header.tenantName")
|
||||
public List selectSpelByHeader() {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DS("#tenantName")
|
||||
public List selectSpelByKey(String tenantName) {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@Override
|
||||
@DS("#tenantName")
|
||||
public List selectSpelByKey(String tenantName) {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DS("#user.tenantName")
|
||||
public List selecSpelByTenant(User user) {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
@Override
|
||||
@DS("#user.tenantName")
|
||||
public List selecSpelByTenant(User user) {
|
||||
return userMapper.selectUsers();
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
package com.baomidou.samples.spel.test;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.baomidou.samples.spel.Application;
|
||||
import com.baomidou.samples.spel.entity.User;
|
||||
import com.baomidou.samples.spel.service.UserService;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -19,51 +15,56 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class ApplicationTest {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private HttpSession session;
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private HttpSession session;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
}
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectSpelBySession() {
|
||||
session.setAttribute("tenantName", "tenant1");
|
||||
userService.selectSpelBySession();
|
||||
}
|
||||
@Test
|
||||
public void selectSpelBySession() {
|
||||
session.setAttribute("tenantName", "tenant1");
|
||||
userService.selectSpelBySession();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectSpelByHeader() throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/users/header")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("tenantName", "tenant1")
|
||||
)
|
||||
.andDo(print()).andExpect(status().isOk())
|
||||
.andReturn().getResponse()
|
||||
.getContentAsString();
|
||||
}
|
||||
@Test
|
||||
public void selectSpelByHeader() throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/users/header")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.header("tenantName", "tenant1")
|
||||
)
|
||||
.andDo(print()).andExpect(status().isOk())
|
||||
.andReturn().getResponse()
|
||||
.getContentAsString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectSpelByKey() {
|
||||
userService.selectSpelByKey("tenant1");
|
||||
}
|
||||
@Test
|
||||
public void selectSpelByKey() {
|
||||
userService.selectSpelByKey("tenant1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selecSpelByTenant() {
|
||||
User user = new User();
|
||||
user.setTenantName("tenant2");
|
||||
userService.selecSpelByTenant(user);
|
||||
}
|
||||
@Test
|
||||
public void selecSpelByTenant() {
|
||||
User user = new User();
|
||||
user.setTenantName("tenant2");
|
||||
userService.selecSpelByTenant(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,65 +3,66 @@ package com.baomidou.samples.load;
|
||||
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
return new AbstractJdbcDataSourceProvider("org.h2.Driver", "jdbc:h2:mem:test", "sa", "") {
|
||||
@Override
|
||||
protected Map<String, DataSourceProperty> executeStmt(Statement statement)
|
||||
throws SQLException {
|
||||
//*************** 实际运行应直接从库中查出,演示所以需要先插入数据***************
|
||||
statement.execute("CREATE TABLE IF NOT EXISTS `DB`\n"
|
||||
+ "(\n"
|
||||
+ " `name` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `username` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `password` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `url` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `driver` VARCHAR(30) NULL DEFAULT NULL\n"
|
||||
+ ")");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('master','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_1','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_2','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_3','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
Map<String, DataSourceProperty> map = new HashMap<>();
|
||||
//*************** ↑↑↑↑↑↑↑ END ***************
|
||||
@Bean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
return new AbstractJdbcDataSourceProvider("org.h2.Driver", "jdbc:h2:mem:test", "sa", "") {
|
||||
@Override
|
||||
protected Map<String, DataSourceProperty> executeStmt(Statement statement)
|
||||
throws SQLException {
|
||||
//*************** 实际运行应直接从库中查出,演示所以需要先插入数据***************
|
||||
statement.execute("CREATE TABLE IF NOT EXISTS `DB`\n"
|
||||
+ "(\n"
|
||||
+ " `name` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `username` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `password` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `url` VARCHAR(30) NULL DEFAULT NULL,\n"
|
||||
+ " `driver` VARCHAR(30) NULL DEFAULT NULL\n"
|
||||
+ ")");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('master','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_1','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_2','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
statement.executeUpdate(
|
||||
"insert into DB values ('slave_3','sa','','jdbc:h2:mem:test','org.h2.Driver')");
|
||||
Map<String, DataSourceProperty> map = new HashMap<>();
|
||||
//*************** ↑↑↑↑↑↑↑ END ***************
|
||||
|
||||
ResultSet rs = statement.executeQuery("select * from DB");
|
||||
while (rs.next()) {
|
||||
String name = rs.getString("name");
|
||||
String username = rs.getString("username");
|
||||
String password = rs.getString("password");
|
||||
String url = rs.getString("url");
|
||||
String driver = rs.getString("driver");
|
||||
DataSourceProperty property = new DataSourceProperty();
|
||||
property.setUsername(username);
|
||||
property.setPassword(password);
|
||||
property.setUrl(url);
|
||||
property.setDriverClassName(driver);
|
||||
map.put(name, property);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
ResultSet rs = statement.executeQuery("select * from DB");
|
||||
while (rs.next()) {
|
||||
String name = rs.getString("name");
|
||||
String username = rs.getString("username");
|
||||
String password = rs.getString("password");
|
||||
String url = rs.getString("url");
|
||||
String driver = rs.getString("driver");
|
||||
DataSourceProperty property = new DataSourceProperty();
|
||||
property.setUsername(username);
|
||||
property.setPassword(password);
|
||||
property.setUrl(url);
|
||||
property.setDriverClassName(driver);
|
||||
map.put(name, property);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -16,10 +16,11 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource;
|
||||
|
||||
import org.springframework.jdbc.datasource.AbstractDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.jdbc.datasource.AbstractDataSource;
|
||||
|
||||
/**
|
||||
* 抽象动态获取数据源
|
||||
@ -29,34 +30,34 @@ import org.springframework.jdbc.datasource.AbstractDataSource;
|
||||
*/
|
||||
public abstract class AbstractRoutingDataSource extends AbstractDataSource {
|
||||
|
||||
/**
|
||||
* 子类实现决定最终数据源
|
||||
*
|
||||
* @return 数据源
|
||||
*/
|
||||
protected abstract DataSource determineDataSource();
|
||||
/**
|
||||
* 子类实现决定最终数据源
|
||||
*
|
||||
* @return 数据源
|
||||
*/
|
||||
protected abstract DataSource determineDataSource();
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return determineDataSource().getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String username, String password) throws SQLException {
|
||||
return determineDataSource().getConnection(username, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
if (iface.isInstance(this)) {
|
||||
return (T) this;
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return determineDataSource().getConnection();
|
||||
}
|
||||
return determineDataSource().unwrap(iface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return (iface.isInstance(this) || determineDataSource().isWrapperFor(iface));
|
||||
}
|
||||
@Override
|
||||
public Connection getConnection(String username, String password) throws SQLException {
|
||||
return determineDataSource().getConnection(username, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
if (iface.isInstance(this)) {
|
||||
return (T) this;
|
||||
}
|
||||
return determineDataSource().unwrap(iface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return (iface.isInstance(this) || determineDataSource().isWrapperFor(iface));
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,10 @@ package com.baomidou.dynamic.datasource;
|
||||
import com.baomidou.dynamic.datasource.matcher.ExpressionMatcher;
|
||||
import com.baomidou.dynamic.datasource.matcher.Matcher;
|
||||
import com.baomidou.dynamic.datasource.matcher.RegexMatcher;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 基于多种策略的自动切换数据源
|
||||
@ -31,24 +32,24 @@ import lombok.Getter;
|
||||
*/
|
||||
public class DynamicDataSourceConfigure {
|
||||
|
||||
@Getter
|
||||
private List<Matcher> matchers = new LinkedList<>();
|
||||
@Getter
|
||||
private List<Matcher> matchers = new LinkedList<>();
|
||||
|
||||
private DynamicDataSourceConfigure() {
|
||||
}
|
||||
private DynamicDataSourceConfigure() {
|
||||
}
|
||||
|
||||
public static DynamicDataSourceConfigure config() {
|
||||
return new DynamicDataSourceConfigure();
|
||||
}
|
||||
public static DynamicDataSourceConfigure config() {
|
||||
return new DynamicDataSourceConfigure();
|
||||
}
|
||||
|
||||
public DynamicDataSourceConfigure regexMatchers(String pattern, String ds) {
|
||||
matchers.add(new RegexMatcher(pattern, ds));
|
||||
return this;
|
||||
}
|
||||
public DynamicDataSourceConfigure regexMatchers(String pattern, String ds) {
|
||||
matchers.add(new RegexMatcher(pattern, ds));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DynamicDataSourceConfigure expressionMatchers(String expression, String ds) {
|
||||
matchers.add(new ExpressionMatcher(expression, ds));
|
||||
return this;
|
||||
}
|
||||
public DynamicDataSourceConfigure expressionMatchers(String expression, String ds) {
|
||||
matchers.add(new ExpressionMatcher(expression, ds));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,10 +17,11 @@
|
||||
package com.baomidou.dynamic.datasource;
|
||||
|
||||
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 分组数据源
|
||||
@ -31,30 +32,30 @@ import lombok.Data;
|
||||
@Data
|
||||
public class DynamicGroupDataSource {
|
||||
|
||||
private String groupName;
|
||||
private String groupName;
|
||||
|
||||
private DynamicDataSourceStrategy dynamicDataSourceStrategy;
|
||||
private DynamicDataSourceStrategy dynamicDataSourceStrategy;
|
||||
|
||||
private List<DataSource> dataSources = new LinkedList<>();
|
||||
private List<DataSource> dataSources = new LinkedList<>();
|
||||
|
||||
public DynamicGroupDataSource(String groupName, DynamicDataSourceStrategy dynamicDataSourceStrategy) {
|
||||
this.groupName = groupName;
|
||||
this.dynamicDataSourceStrategy = dynamicDataSourceStrategy;
|
||||
}
|
||||
public DynamicGroupDataSource(String groupName, DynamicDataSourceStrategy dynamicDataSourceStrategy) {
|
||||
this.groupName = groupName;
|
||||
this.dynamicDataSourceStrategy = dynamicDataSourceStrategy;
|
||||
}
|
||||
|
||||
public void addDatasource(DataSource dataSource) {
|
||||
dataSources.add(dataSource);
|
||||
}
|
||||
public void addDatasource(DataSource dataSource) {
|
||||
dataSources.add(dataSource);
|
||||
}
|
||||
|
||||
public void removeDatasource(DataSource dataSource) {
|
||||
dataSources.remove(dataSource);
|
||||
}
|
||||
public void removeDatasource(DataSource dataSource) {
|
||||
dataSources.remove(dataSource);
|
||||
}
|
||||
|
||||
public DataSource determineDataSource() {
|
||||
return dynamicDataSourceStrategy.determineDataSource(dataSources);
|
||||
}
|
||||
public DataSource determineDataSource() {
|
||||
return dynamicDataSourceStrategy.determineDataSource(dataSources);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return dataSources.size();
|
||||
}
|
||||
public int size() {
|
||||
return dataSources.size();
|
||||
}
|
||||
}
|
||||
|
@ -21,18 +21,19 @@ import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import com.p6spy.engine.spy.P6DataSource;
|
||||
import io.seata.rm.datasource.DataSourceProxy;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 核心动态数据源组件
|
||||
@ -43,227 +44,227 @@ import org.springframework.util.StringUtils;
|
||||
@Slf4j
|
||||
public class DynamicRoutingDataSource extends AbstractRoutingDataSource implements InitializingBean, DisposableBean {
|
||||
|
||||
private static final String UNDERLINE = "_";
|
||||
private static final String UNDERLINE = "_";
|
||||
|
||||
@Setter
|
||||
private DynamicDataSourceProvider provider;
|
||||
@Setter
|
||||
private String primary;
|
||||
@Setter
|
||||
private boolean strict;
|
||||
@Setter
|
||||
private Class<? extends DynamicDataSourceStrategy> strategy;
|
||||
private boolean p6spy;
|
||||
private boolean seata;
|
||||
/**
|
||||
* 所有数据库
|
||||
*/
|
||||
private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
|
||||
/**
|
||||
* 分组数据库
|
||||
*/
|
||||
private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();
|
||||
@Setter
|
||||
private DynamicDataSourceProvider provider;
|
||||
@Setter
|
||||
private String primary;
|
||||
@Setter
|
||||
private boolean strict;
|
||||
@Setter
|
||||
private Class<? extends DynamicDataSourceStrategy> strategy;
|
||||
private boolean p6spy;
|
||||
private boolean seata;
|
||||
/**
|
||||
* 所有数据库
|
||||
*/
|
||||
private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
|
||||
/**
|
||||
* 分组数据库
|
||||
*/
|
||||
private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public DataSource determineDataSource() {
|
||||
return getDataSource(DynamicDataSourceContextHolder.peek());
|
||||
}
|
||||
|
||||
private DataSource determinePrimaryDataSource() {
|
||||
log.debug("dynamic-datasource switch to the primary datasource");
|
||||
return groupDataSources.containsKey(primary) ? groupDataSources.get(primary).determineDataSource() : dataSourceMap.get(primary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前所有的数据源
|
||||
*
|
||||
* @return 当前所有数据源
|
||||
*/
|
||||
public Map<String, DataSource> getCurrentDataSources() {
|
||||
return dataSourceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取的当前所有的分组数据源
|
||||
*
|
||||
* @return 当前所有的分组数据源
|
||||
*/
|
||||
public Map<String, DynamicGroupDataSource> getCurrentGroupDataSources() {
|
||||
return groupDataSources;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource getDataSource(String ds) {
|
||||
if (StringUtils.isEmpty(ds)) {
|
||||
return determinePrimaryDataSource();
|
||||
} else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {
|
||||
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
|
||||
return groupDataSources.get(ds).determineDataSource();
|
||||
} else if (dataSourceMap.containsKey(ds)) {
|
||||
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
|
||||
return dataSourceMap.get(ds);
|
||||
@Override
|
||||
public DataSource determineDataSource() {
|
||||
return getDataSource(DynamicDataSourceContextHolder.peek());
|
||||
}
|
||||
if (strict) {
|
||||
throw new RuntimeException("dynamic-datasource could not find a datasource named" + ds);
|
||||
}
|
||||
return determinePrimaryDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
* @param dataSource 数据源
|
||||
*/
|
||||
public synchronized void addDataSource(String ds, DataSource dataSource) {
|
||||
if (!dataSourceMap.containsKey(ds)) {
|
||||
dataSource = wrapDataSource(ds, dataSource);
|
||||
dataSourceMap.put(ds, dataSource);
|
||||
this.addGroupDataSource(ds, dataSource);
|
||||
log.info("dynamic-datasource - load a datasource named [{}] success", ds);
|
||||
} else {
|
||||
log.warn("dynamic-datasource - load a datasource named [{}] failed, because it already exist", ds);
|
||||
private DataSource determinePrimaryDataSource() {
|
||||
log.debug("dynamic-datasource switch to the primary datasource");
|
||||
return groupDataSources.containsKey(primary) ? groupDataSources.get(primary).determineDataSource() : dataSourceMap.get(primary);
|
||||
}
|
||||
}
|
||||
|
||||
private DataSource wrapDataSource(String ds, DataSource dataSource) {
|
||||
if (p6spy) {
|
||||
dataSource = new P6DataSource(dataSource);
|
||||
log.info("dynamic-datasource [{}] wrap p6spy plugin", ds);
|
||||
/**
|
||||
* 获取当前所有的数据源
|
||||
*
|
||||
* @return 当前所有数据源
|
||||
*/
|
||||
public Map<String, DataSource> getCurrentDataSources() {
|
||||
return dataSourceMap;
|
||||
}
|
||||
if (seata) {
|
||||
dataSource = new DataSourceProxy(dataSource);
|
||||
log.info("dynamic-datasource [{}] wrap seata plugin", ds);
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void addGroupDataSource(String ds, DataSource dataSource) {
|
||||
if (ds.contains(UNDERLINE)) {
|
||||
String group = ds.split(UNDERLINE)[0];
|
||||
if (groupDataSources.containsKey(group)) {
|
||||
groupDataSources.get(group).addDatasource(dataSource);
|
||||
} else {
|
||||
/**
|
||||
* 获取的当前所有的分组数据源
|
||||
*
|
||||
* @return 当前所有的分组数据源
|
||||
*/
|
||||
public Map<String, DynamicGroupDataSource> getCurrentGroupDataSources() {
|
||||
return groupDataSources;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource getDataSource(String ds) {
|
||||
if (StringUtils.isEmpty(ds)) {
|
||||
return determinePrimaryDataSource();
|
||||
} else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {
|
||||
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
|
||||
return groupDataSources.get(ds).determineDataSource();
|
||||
} else if (dataSourceMap.containsKey(ds)) {
|
||||
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
|
||||
return dataSourceMap.get(ds);
|
||||
}
|
||||
if (strict) {
|
||||
throw new RuntimeException("dynamic-datasource could not find a datasource named" + ds);
|
||||
}
|
||||
return determinePrimaryDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
* @param dataSource 数据源
|
||||
*/
|
||||
public synchronized void addDataSource(String ds, DataSource dataSource) {
|
||||
if (!dataSourceMap.containsKey(ds)) {
|
||||
dataSource = wrapDataSource(ds, dataSource);
|
||||
dataSourceMap.put(ds, dataSource);
|
||||
this.addGroupDataSource(ds, dataSource);
|
||||
log.info("dynamic-datasource - load a datasource named [{}] success", ds);
|
||||
} else {
|
||||
log.warn("dynamic-datasource - load a datasource named [{}] failed, because it already exist", ds);
|
||||
}
|
||||
}
|
||||
|
||||
private DataSource wrapDataSource(String ds, DataSource dataSource) {
|
||||
if (p6spy) {
|
||||
dataSource = new P6DataSource(dataSource);
|
||||
log.info("dynamic-datasource [{}] wrap p6spy plugin", ds);
|
||||
}
|
||||
if (seata) {
|
||||
dataSource = new DataSourceProxy(dataSource);
|
||||
log.info("dynamic-datasource [{}] wrap seata plugin", ds);
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void addGroupDataSource(String ds, DataSource dataSource) {
|
||||
if (ds.contains(UNDERLINE)) {
|
||||
String group = ds.split(UNDERLINE)[0];
|
||||
if (groupDataSources.containsKey(group)) {
|
||||
groupDataSources.get(group).addDatasource(dataSource);
|
||||
} else {
|
||||
try {
|
||||
DynamicGroupDataSource groupDatasource = new DynamicGroupDataSource(group, strategy.newInstance());
|
||||
groupDatasource.addDatasource(dataSource);
|
||||
groupDataSources.put(group, groupDatasource);
|
||||
} catch (Exception e) {
|
||||
log.error("dynamic-datasource - add the datasource named [{}] error", ds, e);
|
||||
dataSourceMap.remove(ds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
*/
|
||||
public synchronized void removeDataSource(String ds) {
|
||||
if (!StringUtils.hasText(ds)) {
|
||||
throw new RuntimeException("remove parameter could not be empty");
|
||||
}
|
||||
if (primary.equals(ds)) {
|
||||
throw new RuntimeException("could not remove primary datasource");
|
||||
}
|
||||
if (dataSourceMap.containsKey(ds)) {
|
||||
DataSource dataSource = dataSourceMap.get(ds);
|
||||
try {
|
||||
closeDataSource(ds, dataSource);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("dynamic-datasource - remove the database named " + ds + " failed", e);
|
||||
}
|
||||
dataSourceMap.remove(ds);
|
||||
if (ds.contains(UNDERLINE)) {
|
||||
String group = ds.split(UNDERLINE)[0];
|
||||
if (groupDataSources.containsKey(group)) {
|
||||
groupDataSources.get(group).removeDatasource(dataSource);
|
||||
}
|
||||
}
|
||||
log.info("dynamic-datasource - remove the database named [{}] success", ds);
|
||||
} else {
|
||||
log.warn("dynamic-datasource - could not find a database named [{}]", ds);
|
||||
}
|
||||
}
|
||||
|
||||
public void setP6spy(boolean p6spy) {
|
||||
if (p6spy) {
|
||||
try {
|
||||
Class.forName("com.p6spy.engine.spy.P6DataSource");
|
||||
log.info("dynamic-datasource detect P6SPY plugin and enabled it");
|
||||
this.p6spy = true;
|
||||
} catch (Exception e) {
|
||||
log.warn("dynamic-datasource enabled P6SPY ,however without p6spy dependency");
|
||||
}
|
||||
} else {
|
||||
this.p6spy = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSeata(boolean seata) {
|
||||
if (seata) {
|
||||
try {
|
||||
Class.forName("io.seata.rm.datasource.DataSourceProxy");
|
||||
this.seata = true;
|
||||
log.info("dynamic-datasource detect ALIBABA SEATA and enabled it");
|
||||
} catch (Exception e) {
|
||||
this.seata = false;
|
||||
log.warn("dynamic-datasource enabled ALIBABA SEATA ,however without seata dependency");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
log.info("dynamic-datasource start closing ....");
|
||||
for (Map.Entry<String, DataSource> item : dataSourceMap.entrySet()) {
|
||||
closeDataSource(item.getKey(), item.getValue());
|
||||
}
|
||||
log.info("dynamic-datasource all closed success,bye");
|
||||
}
|
||||
|
||||
private void closeDataSource(String name, DataSource dataSource)
|
||||
throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
|
||||
if (seata) {
|
||||
DataSourceProxy dataSourceProxy = (DataSourceProxy) dataSource;
|
||||
dataSource = dataSourceProxy.getTargetDataSource();
|
||||
}
|
||||
if (p6spy) {
|
||||
Field realDataSourceField = P6DataSource.class.getDeclaredField("realDataSource");
|
||||
realDataSourceField.setAccessible(true);
|
||||
dataSource = (DataSource) realDataSourceField.get(dataSource);
|
||||
}
|
||||
Class<? extends DataSource> clazz = dataSource.getClass();
|
||||
try {
|
||||
DynamicGroupDataSource groupDatasource = new DynamicGroupDataSource(group, strategy.newInstance());
|
||||
groupDatasource.addDatasource(dataSource);
|
||||
groupDataSources.put(group, groupDatasource);
|
||||
} catch (Exception e) {
|
||||
log.error("dynamic-datasource - add the datasource named [{}] error", ds, e);
|
||||
dataSourceMap.remove(ds);
|
||||
Method closeMethod = clazz.getDeclaredMethod("close");
|
||||
closeMethod.invoke(dataSource);
|
||||
} catch (NoSuchMethodException e) {
|
||||
log.warn("dynamic-datasource close the datasource named [{}] failed,", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据源
|
||||
*
|
||||
* @param ds 数据源名称
|
||||
*/
|
||||
public synchronized void removeDataSource(String ds) {
|
||||
if (!StringUtils.hasText(ds)) {
|
||||
throw new RuntimeException("remove parameter could not be empty");
|
||||
}
|
||||
if (primary.equals(ds)) {
|
||||
throw new RuntimeException("could not remove primary datasource");
|
||||
}
|
||||
if (dataSourceMap.containsKey(ds)) {
|
||||
DataSource dataSource = dataSourceMap.get(ds);
|
||||
try {
|
||||
closeDataSource(ds, dataSource);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("dynamic-datasource - remove the database named " + ds + " failed", e);
|
||||
}
|
||||
dataSourceMap.remove(ds);
|
||||
if (ds.contains(UNDERLINE)) {
|
||||
String group = ds.split(UNDERLINE)[0];
|
||||
if (groupDataSources.containsKey(group)) {
|
||||
groupDataSources.get(group).removeDatasource(dataSource);
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Map<String, DataSource> dataSources = provider.loadDataSources();
|
||||
// 添加并分组数据源
|
||||
for (Map.Entry<String, DataSource> dsItem : dataSources.entrySet()) {
|
||||
addDataSource(dsItem.getKey(), dsItem.getValue());
|
||||
}
|
||||
// 检测默认数据源设置
|
||||
if (groupDataSources.containsKey(primary)) {
|
||||
log.info("dynamic-datasource initial loaded [{}] datasource,primary group datasource named [{}]", dataSources.size(), primary);
|
||||
} else if (dataSourceMap.containsKey(primary)) {
|
||||
log.info("dynamic-datasource initial loaded [{}] datasource,primary datasource named [{}]", dataSources.size(), primary);
|
||||
} else {
|
||||
throw new RuntimeException("dynamic-datasource Please check the setting of primary");
|
||||
}
|
||||
}
|
||||
log.info("dynamic-datasource - remove the database named [{}] success", ds);
|
||||
} else {
|
||||
log.warn("dynamic-datasource - could not find a database named [{}]", ds);
|
||||
}
|
||||
}
|
||||
|
||||
public void setP6spy(boolean p6spy) {
|
||||
if (p6spy) {
|
||||
try {
|
||||
Class.forName("com.p6spy.engine.spy.P6DataSource");
|
||||
log.info("dynamic-datasource detect P6SPY plugin and enabled it");
|
||||
this.p6spy = true;
|
||||
} catch (Exception e) {
|
||||
log.warn("dynamic-datasource enabled P6SPY ,however without p6spy dependency");
|
||||
}
|
||||
} else {
|
||||
this.p6spy = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSeata(boolean seata) {
|
||||
if (seata) {
|
||||
try {
|
||||
Class.forName("io.seata.rm.datasource.DataSourceProxy");
|
||||
this.seata = true;
|
||||
log.info("dynamic-datasource detect ALIBABA SEATA and enabled it");
|
||||
} catch (Exception e) {
|
||||
this.seata = false;
|
||||
log.warn("dynamic-datasource enabled ALIBABA SEATA ,however without seata dependency");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
log.info("dynamic-datasource start closing ....");
|
||||
for (Map.Entry<String, DataSource> item : dataSourceMap.entrySet()) {
|
||||
closeDataSource(item.getKey(), item.getValue());
|
||||
}
|
||||
log.info("dynamic-datasource all closed success,bye");
|
||||
}
|
||||
|
||||
private void closeDataSource(String name, DataSource dataSource)
|
||||
throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
|
||||
if (seata) {
|
||||
DataSourceProxy dataSourceProxy = (DataSourceProxy) dataSource;
|
||||
dataSource = dataSourceProxy.getTargetDataSource();
|
||||
}
|
||||
if (p6spy) {
|
||||
Field realDataSourceField = P6DataSource.class.getDeclaredField("realDataSource");
|
||||
realDataSourceField.setAccessible(true);
|
||||
dataSource = (DataSource) realDataSourceField.get(dataSource);
|
||||
}
|
||||
Class<? extends DataSource> clazz = dataSource.getClass();
|
||||
try {
|
||||
Method closeMethod = clazz.getDeclaredMethod("close");
|
||||
closeMethod.invoke(dataSource);
|
||||
} catch (NoSuchMethodException e) {
|
||||
log.warn("dynamic-datasource close the datasource named [{}] failed,", name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Map<String, DataSource> dataSources = provider.loadDataSources();
|
||||
// 添加并分组数据源
|
||||
for (Map.Entry<String, DataSource> dsItem : dataSources.entrySet()) {
|
||||
addDataSource(dsItem.getKey(), dsItem.getValue());
|
||||
}
|
||||
// 检测默认数据源设置
|
||||
if (groupDataSources.containsKey(primary)) {
|
||||
log.info("dynamic-datasource initial loaded [{}] datasource,primary group datasource named [{}]", dataSources.size(), primary);
|
||||
} else if (dataSourceMap.containsKey(primary)) {
|
||||
log.info("dynamic-datasource initial loaded [{}] datasource,primary datasource named [{}]", dataSources.size(), primary);
|
||||
} else {
|
||||
throw new RuntimeException("dynamic-datasource Please check the setting of primary");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,11 +17,7 @@
|
||||
package com.baomidou.dynamic.datasource.annotation;
|
||||
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* The core Annotation to switch datasource. It can be annotate at class or method.
|
||||
@ -34,10 +30,10 @@ import java.lang.annotation.Target;
|
||||
@Documented
|
||||
public @interface DS {
|
||||
|
||||
/**
|
||||
* groupName or specific database name or spring SPEL name.
|
||||
*
|
||||
* @return the database you want to switch
|
||||
*/
|
||||
String value();
|
||||
/**
|
||||
* groupName or specific database name or spring SPEL name.
|
||||
*
|
||||
* @return the database you want to switch
|
||||
*/
|
||||
String value();
|
||||
}
|
@ -16,9 +16,10 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.aop;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
@ -26,22 +27,22 @@ import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
*/
|
||||
public class DynamicAspectJExpressionPointcut extends AspectJExpressionPointcut {
|
||||
|
||||
private Map<String, String> matchesCache;
|
||||
private Map<String, String> matchesCache;
|
||||
|
||||
private String ds;
|
||||
private String ds;
|
||||
|
||||
public DynamicAspectJExpressionPointcut(String expression, String ds, Map<String, String> matchesCache) {
|
||||
this.ds = ds;
|
||||
this.matchesCache = matchesCache;
|
||||
setExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
boolean matches = super.matches(method, targetClass, beanHasIntroductions);
|
||||
if (matches) {
|
||||
matchesCache.put(targetClass.getName() + "." + method.getName(), ds);
|
||||
public DynamicAspectJExpressionPointcut(String expression, String ds, Map<String, String> matchesCache) {
|
||||
this.ds = ds;
|
||||
this.matchesCache = matchesCache;
|
||||
setExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
boolean matches = super.matches(method, targetClass, beanHasIntroductions);
|
||||
if (matches) {
|
||||
matchesCache.put(targetClass.getName() + "." + method.getName(), ds);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
}
|
@ -21,10 +21,6 @@ import com.baomidou.dynamic.datasource.matcher.Matcher;
|
||||
import com.baomidou.dynamic.datasource.matcher.RegexMatcher;
|
||||
import com.baomidou.dynamic.datasource.processor.DsProcessor;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Setter;
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@ -36,90 +32,95 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class DynamicDataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* The identification of SPEL
|
||||
*/
|
||||
private static final String DYNAMIC_PREFIX = "#";
|
||||
/**
|
||||
* The identification of SPEL
|
||||
*/
|
||||
private static final String DYNAMIC_PREFIX = "#";
|
||||
|
||||
@Setter
|
||||
private DsProcessor dsProcessor;
|
||||
@Setter
|
||||
private DsProcessor dsProcessor;
|
||||
|
||||
private Advice advice;
|
||||
private Advice advice;
|
||||
|
||||
private Pointcut pointcut;
|
||||
private Pointcut pointcut;
|
||||
|
||||
private Map<String, String> matchesCache = new HashMap<>();
|
||||
private Map<String, String> matchesCache = new HashMap<>();
|
||||
|
||||
public DynamicDataSourceAdvisor(List<Matcher> matchers) {
|
||||
this.pointcut = buildPointcut(matchers);
|
||||
this.advice = buildAdvice();
|
||||
}
|
||||
|
||||
private Advice buildAdvice() {
|
||||
return new MethodInterceptor() {
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
try {
|
||||
Method method = invocation.getMethod();
|
||||
String methodPath = invocation.getThis().getClass().getName() + "." + method.getName();
|
||||
String key = matchesCache.get(methodPath);
|
||||
if (key != null && !key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) {
|
||||
key = dsProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
DynamicDataSourceContextHolder.push(key);
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
DynamicDataSourceContextHolder.poll();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (this.advice instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
|
||||
public DynamicDataSourceAdvisor(List<Matcher> matchers) {
|
||||
this.pointcut = buildPointcut(matchers);
|
||||
this.advice = buildAdvice();
|
||||
}
|
||||
}
|
||||
|
||||
private Pointcut buildPointcut(List<Matcher> matchers) {
|
||||
ComposablePointcut composablePointcut = null;
|
||||
for (Matcher matcher : matchers) {
|
||||
if (matcher instanceof RegexMatcher) {
|
||||
RegexMatcher regexMatcher = (RegexMatcher) matcher;
|
||||
Pointcut pointcut = new DynamicJdkRegexpMethodPointcut(regexMatcher.getPattern(), regexMatcher.getDs(), matchesCache);
|
||||
if (composablePointcut == null) {
|
||||
composablePointcut = new ComposablePointcut(pointcut);
|
||||
} else {
|
||||
composablePointcut.union(pointcut);
|
||||
}
|
||||
} else {
|
||||
ExpressionMatcher expressionMatcher = (ExpressionMatcher) matcher;
|
||||
Pointcut pointcut = new DynamicAspectJExpressionPointcut(expressionMatcher.getExpression(), expressionMatcher.getDs(),
|
||||
matchesCache);
|
||||
if (composablePointcut == null) {
|
||||
composablePointcut = new ComposablePointcut(pointcut);
|
||||
} else {
|
||||
composablePointcut.union(pointcut);
|
||||
}
|
||||
}
|
||||
private Advice buildAdvice() {
|
||||
return new MethodInterceptor() {
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
try {
|
||||
Method method = invocation.getMethod();
|
||||
String methodPath = invocation.getThis().getClass().getName() + "." + method.getName();
|
||||
String key = matchesCache.get(methodPath);
|
||||
if (key != null && !key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) {
|
||||
key = dsProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
DynamicDataSourceContextHolder.push(key);
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
DynamicDataSourceContextHolder.poll();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (this.advice instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private Pointcut buildPointcut(List<Matcher> matchers) {
|
||||
ComposablePointcut composablePointcut = null;
|
||||
for (Matcher matcher : matchers) {
|
||||
if (matcher instanceof RegexMatcher) {
|
||||
RegexMatcher regexMatcher = (RegexMatcher) matcher;
|
||||
Pointcut pointcut = new DynamicJdkRegexpMethodPointcut(regexMatcher.getPattern(), regexMatcher.getDs(), matchesCache);
|
||||
if (composablePointcut == null) {
|
||||
composablePointcut = new ComposablePointcut(pointcut);
|
||||
} else {
|
||||
composablePointcut.union(pointcut);
|
||||
}
|
||||
} else {
|
||||
ExpressionMatcher expressionMatcher = (ExpressionMatcher) matcher;
|
||||
Pointcut pointcut = new DynamicAspectJExpressionPointcut(expressionMatcher.getExpression(), expressionMatcher.getDs(),
|
||||
matchesCache);
|
||||
if (composablePointcut == null) {
|
||||
composablePointcut = new ComposablePointcut(pointcut);
|
||||
} else {
|
||||
composablePointcut.union(pointcut);
|
||||
}
|
||||
}
|
||||
}
|
||||
return composablePointcut;
|
||||
}
|
||||
return composablePointcut;
|
||||
}
|
||||
}
|
||||
|
@ -32,37 +32,37 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class DynamicDataSourceAnnotationAdvisor extends AbstractPointcutAdvisor implements
|
||||
BeanFactoryAware {
|
||||
BeanFactoryAware {
|
||||
|
||||
private Advice advice;
|
||||
private Advice advice;
|
||||
|
||||
private Pointcut pointcut;
|
||||
private Pointcut pointcut;
|
||||
|
||||
public DynamicDataSourceAnnotationAdvisor(@NonNull DynamicDataSourceAnnotationInterceptor dynamicDataSourceAnnotationInterceptor) {
|
||||
this.advice = dynamicDataSourceAnnotationInterceptor;
|
||||
this.pointcut = buildPointcut();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (this.advice instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
|
||||
public DynamicDataSourceAnnotationAdvisor(@NonNull DynamicDataSourceAnnotationInterceptor dynamicDataSourceAnnotationInterceptor) {
|
||||
this.advice = dynamicDataSourceAnnotationInterceptor;
|
||||
this.pointcut = buildPointcut();
|
||||
}
|
||||
}
|
||||
|
||||
private Pointcut buildPointcut() {
|
||||
Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);
|
||||
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(DS.class);
|
||||
return new ComposablePointcut(cpc).union(mpc);
|
||||
}
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (this.advice instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private Pointcut buildPointcut() {
|
||||
Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);
|
||||
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(DS.class);
|
||||
return new ComposablePointcut(cpc).union(mpc);
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,13 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.dynamic.datasource.processor.DsProcessor;
|
||||
import com.baomidou.dynamic.datasource.support.DataSourceClassResolver;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import java.lang.reflect.Method;
|
||||
import lombok.Setter;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Core Interceptor of Dynamic Datasource
|
||||
*
|
||||
@ -34,29 +35,29 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
*/
|
||||
public class DynamicDataSourceAnnotationInterceptor implements MethodInterceptor {
|
||||
|
||||
/**
|
||||
* The identification of SPEL.
|
||||
*/
|
||||
private static final String DYNAMIC_PREFIX = "#";
|
||||
private static final DataSourceClassResolver RESOLVER = new DataSourceClassResolver();
|
||||
@Setter
|
||||
private DsProcessor dsProcessor;
|
||||
/**
|
||||
* The identification of SPEL.
|
||||
*/
|
||||
private static final String DYNAMIC_PREFIX = "#";
|
||||
private static final DataSourceClassResolver RESOLVER = new DataSourceClassResolver();
|
||||
@Setter
|
||||
private DsProcessor dsProcessor;
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
try {
|
||||
DynamicDataSourceContextHolder.push(determineDatasource(invocation));
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
DynamicDataSourceContextHolder.poll();
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
try {
|
||||
DynamicDataSourceContextHolder.push(determineDatasource(invocation));
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
DynamicDataSourceContextHolder.poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String determineDatasource(MethodInvocation invocation) throws Throwable {
|
||||
Method method = invocation.getMethod();
|
||||
DS ds = method.isAnnotationPresent(DS.class) ? method.getAnnotation(DS.class)
|
||||
: AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);
|
||||
String key = ds.value();
|
||||
return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor.determineDatasource(invocation, key) : key;
|
||||
}
|
||||
private String determineDatasource(MethodInvocation invocation) throws Throwable {
|
||||
Method method = invocation.getMethod();
|
||||
DS ds = method.isAnnotationPresent(DS.class) ? method.getAnnotation(DS.class)
|
||||
: AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);
|
||||
String key = ds.value();
|
||||
return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor.determineDatasource(invocation, key) : key;
|
||||
}
|
||||
}
|
@ -16,31 +16,32 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.aop;
|
||||
|
||||
import java.util.Map;
|
||||
import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class DynamicJdkRegexpMethodPointcut extends JdkRegexpMethodPointcut {
|
||||
|
||||
private Map<String, String> matchesCache;
|
||||
private Map<String, String> matchesCache;
|
||||
|
||||
private String ds;
|
||||
private String ds;
|
||||
|
||||
public DynamicJdkRegexpMethodPointcut(String pattern, String ds, Map<String, String> matchesCache) {
|
||||
this.ds = ds;
|
||||
this.matchesCache = matchesCache;
|
||||
setPattern(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(String pattern, int patternIndex) {
|
||||
boolean matches = super.matches(pattern, patternIndex);
|
||||
if (matches) {
|
||||
matchesCache.put(pattern, ds);
|
||||
public DynamicJdkRegexpMethodPointcut(String pattern, String ds, Map<String, String> matchesCache) {
|
||||
this.ds = ds;
|
||||
this.matchesCache = matchesCache;
|
||||
setPattern(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(String pattern, int patternIndex) {
|
||||
boolean matches = super.matches(pattern, patternIndex);
|
||||
if (matches) {
|
||||
matchesCache.put(pattern, ds);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
}
|
@ -18,11 +18,12 @@ package com.baomidou.dynamic.datasource.creator;
|
||||
|
||||
import com.baomidou.dynamic.datasource.exception.ErrorCreateDataSourceException;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 基础数据源创建器
|
||||
*
|
||||
@ -33,62 +34,62 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@Slf4j
|
||||
public class BasicDataSourceCreator {
|
||||
|
||||
private static Method createMethod;
|
||||
private static Method typeMethod;
|
||||
private static Method urlMethod;
|
||||
private static Method usernameMethod;
|
||||
private static Method passwordMethod;
|
||||
private static Method driverClassNameMethod;
|
||||
private static Method buildMethod;
|
||||
private static Method createMethod;
|
||||
private static Method typeMethod;
|
||||
private static Method urlMethod;
|
||||
private static Method usernameMethod;
|
||||
private static Method passwordMethod;
|
||||
private static Method driverClassNameMethod;
|
||||
private static Method buildMethod;
|
||||
|
||||
static {
|
||||
//to support springboot 1.5 and 2.x
|
||||
Class<?> builderClass = null;
|
||||
try {
|
||||
builderClass = Class.forName("org.springframework.boot.jdbc.DataSourceBuilder");
|
||||
} catch (Exception ignored) {
|
||||
static {
|
||||
//to support springboot 1.5 and 2.x
|
||||
Class<?> builderClass = null;
|
||||
try {
|
||||
builderClass = Class.forName("org.springframework.boot.jdbc.DataSourceBuilder");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
if (builderClass == null) {
|
||||
try {
|
||||
builderClass = Class.forName("org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder");
|
||||
} catch (Exception e) {
|
||||
log.warn("not in springBoot ENV,could not create BasicDataSourceCreator");
|
||||
}
|
||||
}
|
||||
if (builderClass != null) {
|
||||
try {
|
||||
createMethod = builderClass.getDeclaredMethod("create");
|
||||
typeMethod = builderClass.getDeclaredMethod("type", Class.class);
|
||||
urlMethod = builderClass.getDeclaredMethod("url", String.class);
|
||||
usernameMethod = builderClass.getDeclaredMethod("username", String.class);
|
||||
passwordMethod = builderClass.getDeclaredMethod("password", String.class);
|
||||
driverClassNameMethod = builderClass.getDeclaredMethod("driverClassName", String.class);
|
||||
buildMethod = builderClass.getDeclaredMethod("build");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (builderClass == null) {
|
||||
try {
|
||||
builderClass = Class.forName("org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder");
|
||||
} catch (Exception e) {
|
||||
log.warn("not in springBoot ENV,could not create BasicDataSourceCreator");
|
||||
}
|
||||
}
|
||||
if (builderClass != null) {
|
||||
try {
|
||||
createMethod = builderClass.getDeclaredMethod("create");
|
||||
typeMethod = builderClass.getDeclaredMethod("type", Class.class);
|
||||
urlMethod = builderClass.getDeclaredMethod("url", String.class);
|
||||
usernameMethod = builderClass.getDeclaredMethod("username", String.class);
|
||||
passwordMethod = builderClass.getDeclaredMethod("password", String.class);
|
||||
driverClassNameMethod = builderClass.getDeclaredMethod("driverClassName", String.class);
|
||||
buildMethod = builderClass.getDeclaredMethod("build");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
try {
|
||||
Object o1 = createMethod.invoke(null);
|
||||
Object o2 = typeMethod.invoke(o1, dataSourceProperty.getType());
|
||||
Object o3 = urlMethod.invoke(o2, dataSourceProperty.getUrl());
|
||||
Object o4 = usernameMethod.invoke(o3, dataSourceProperty.getUsername());
|
||||
Object o5 = passwordMethod.invoke(o4, dataSourceProperty.getPassword());
|
||||
Object o6 = driverClassNameMethod.invoke(o5, dataSourceProperty.getDriverClassName());
|
||||
return (DataSource) buildMethod.invoke(o6);
|
||||
} catch (Exception e) {
|
||||
throw new ErrorCreateDataSourceException(
|
||||
"dynamic-datasource create basic database named " + dataSourceProperty.getPoolName() + " error");
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
try {
|
||||
Object o1 = createMethod.invoke(null);
|
||||
Object o2 = typeMethod.invoke(o1, dataSourceProperty.getType());
|
||||
Object o3 = urlMethod.invoke(o2, dataSourceProperty.getUrl());
|
||||
Object o4 = usernameMethod.invoke(o3, dataSourceProperty.getUsername());
|
||||
Object o5 = passwordMethod.invoke(o4, dataSourceProperty.getPassword());
|
||||
Object o6 = driverClassNameMethod.invoke(o5, dataSourceProperty.getDriverClassName());
|
||||
return (DataSource) buildMethod.invoke(o6);
|
||||
} catch (Exception e) {
|
||||
throw new ErrorCreateDataSourceException(
|
||||
"dynamic-datasource create basic database named " + dataSourceProperty.getPoolName() + " error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,16 +16,17 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.creator;
|
||||
|
||||
import static com.baomidou.dynamic.datasource.support.DdConstants.DRUID_DATASOURCE;
|
||||
import static com.baomidou.dynamic.datasource.support.DdConstants.HIKARI_DATASOURCE;
|
||||
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.support.ScriptRunner;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import static com.baomidou.dynamic.datasource.support.DdConstants.DRUID_DATASOURCE;
|
||||
import static com.baomidou.dynamic.datasource.support.DdConstants.HIKARI_DATASOURCE;
|
||||
|
||||
/**
|
||||
* 数据源创建器
|
||||
*
|
||||
@ -36,129 +37,129 @@ import org.springframework.util.StringUtils;
|
||||
@Setter
|
||||
public class DataSourceCreator {
|
||||
|
||||
/**
|
||||
* 是否存在druid
|
||||
*/
|
||||
private static Boolean druidExists = false;
|
||||
/**
|
||||
* 是否存在hikari
|
||||
*/
|
||||
private static Boolean hikariExists = false;
|
||||
/**
|
||||
* 是否存在druid
|
||||
*/
|
||||
private static Boolean druidExists = false;
|
||||
/**
|
||||
* 是否存在hikari
|
||||
*/
|
||||
private static Boolean hikariExists = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName(DRUID_DATASOURCE);
|
||||
druidExists = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
try {
|
||||
Class.forName(HIKARI_DATASOURCE);
|
||||
hikariExists = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private BasicDataSourceCreator basicDataSourceCreator;
|
||||
private JndiDataSourceCreator jndiDataSourceCreator;
|
||||
private HikariDataSourceCreator hikariDataSourceCreator;
|
||||
private DruidDataSourceCreator druidDataSourceCreator;
|
||||
private String globalPublicKey;
|
||||
|
||||
/**
|
||||
* 创建数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源信息
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
DataSource dataSource;
|
||||
//如果是jndi数据源
|
||||
String jndiName = dataSourceProperty.getJndiName();
|
||||
if (jndiName != null && !jndiName.isEmpty()) {
|
||||
dataSource = createJNDIDataSource(jndiName);
|
||||
} else {
|
||||
Class<? extends DataSource> type = dataSourceProperty.getType();
|
||||
if (type == null) {
|
||||
if (druidExists) {
|
||||
dataSource = createDruidDataSource(dataSourceProperty);
|
||||
} else if (hikariExists) {
|
||||
dataSource = createHikariDataSource(dataSourceProperty);
|
||||
} else {
|
||||
dataSource = createBasicDataSource(dataSourceProperty);
|
||||
static {
|
||||
try {
|
||||
Class.forName(DRUID_DATASOURCE);
|
||||
druidExists = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
try {
|
||||
Class.forName(HIKARI_DATASOURCE);
|
||||
hikariExists = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
} else if (DRUID_DATASOURCE.equals(type.getName())) {
|
||||
dataSource = createDruidDataSource(dataSourceProperty);
|
||||
} else if (HIKARI_DATASOURCE.equals(type.getName())) {
|
||||
dataSource = createHikariDataSource(dataSourceProperty);
|
||||
} else {
|
||||
dataSource = createBasicDataSource(dataSourceProperty);
|
||||
}
|
||||
}
|
||||
this.runScrip(dataSourceProperty, dataSource);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void runScrip(DataSourceProperty dataSourceProperty, DataSource dataSource) {
|
||||
String schema = dataSourceProperty.getSchema();
|
||||
String data = dataSourceProperty.getData();
|
||||
if (StringUtils.hasText(schema) || StringUtils.hasText(data)) {
|
||||
ScriptRunner scriptRunner = new ScriptRunner(dataSourceProperty.isContinueOnError(), dataSourceProperty.getSeparator());
|
||||
if (StringUtils.hasText(schema)) {
|
||||
scriptRunner.runScript(dataSource, schema);
|
||||
}
|
||||
if (StringUtils.hasText(data)) {
|
||||
scriptRunner.runScript(dataSource, data);
|
||||
}
|
||||
private BasicDataSourceCreator basicDataSourceCreator;
|
||||
private JndiDataSourceCreator jndiDataSourceCreator;
|
||||
private HikariDataSourceCreator hikariDataSourceCreator;
|
||||
private DruidDataSourceCreator druidDataSourceCreator;
|
||||
private String globalPublicKey;
|
||||
|
||||
/**
|
||||
* 创建数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源信息
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
DataSource dataSource;
|
||||
//如果是jndi数据源
|
||||
String jndiName = dataSourceProperty.getJndiName();
|
||||
if (jndiName != null && !jndiName.isEmpty()) {
|
||||
dataSource = createJNDIDataSource(jndiName);
|
||||
} else {
|
||||
Class<? extends DataSource> type = dataSourceProperty.getType();
|
||||
if (type == null) {
|
||||
if (druidExists) {
|
||||
dataSource = createDruidDataSource(dataSourceProperty);
|
||||
} else if (hikariExists) {
|
||||
dataSource = createHikariDataSource(dataSourceProperty);
|
||||
} else {
|
||||
dataSource = createBasicDataSource(dataSourceProperty);
|
||||
}
|
||||
} else if (DRUID_DATASOURCE.equals(type.getName())) {
|
||||
dataSource = createDruidDataSource(dataSourceProperty);
|
||||
} else if (HIKARI_DATASOURCE.equals(type.getName())) {
|
||||
dataSource = createHikariDataSource(dataSourceProperty);
|
||||
} else {
|
||||
dataSource = createBasicDataSource(dataSourceProperty);
|
||||
}
|
||||
}
|
||||
this.runScrip(dataSourceProperty, dataSource);
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createBasicDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
private void runScrip(DataSourceProperty dataSourceProperty, DataSource dataSource) {
|
||||
String schema = dataSourceProperty.getSchema();
|
||||
String data = dataSourceProperty.getData();
|
||||
if (StringUtils.hasText(schema) || StringUtils.hasText(data)) {
|
||||
ScriptRunner scriptRunner = new ScriptRunner(dataSourceProperty.isContinueOnError(), dataSourceProperty.getSeparator());
|
||||
if (StringUtils.hasText(schema)) {
|
||||
scriptRunner.runScript(dataSource, schema);
|
||||
}
|
||||
if (StringUtils.hasText(data)) {
|
||||
scriptRunner.runScript(dataSource, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return basicDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建JNDI数据源
|
||||
*
|
||||
* @param jndiName jndi数据源名称
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createJNDIDataSource(String jndiName) {
|
||||
return jndiDataSourceCreator.createDataSource(jndiName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Druid数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDruidDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createBasicDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
}
|
||||
return basicDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
return druidDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Hikari数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
* @author 离世庭院 小锅盖
|
||||
*/
|
||||
public DataSource createHikariDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
/**
|
||||
* 创建JNDI数据源
|
||||
*
|
||||
* @param jndiName jndi数据源名称
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createJNDIDataSource(String jndiName) {
|
||||
return jndiDataSourceCreator.createDataSource(jndiName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Druid数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDruidDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
}
|
||||
return druidDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Hikari数据源
|
||||
*
|
||||
* @param dataSourceProperty 数据源参数
|
||||
* @return 数据源
|
||||
* @author 离世庭院 小锅盖
|
||||
*/
|
||||
public DataSource createHikariDataSource(DataSourceProperty dataSourceProperty) {
|
||||
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
|
||||
dataSourceProperty.setPublicKey(globalPublicKey);
|
||||
}
|
||||
return hikariDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
return hikariDataSourceCreator.createDataSource(dataSourceProperty);
|
||||
}
|
||||
}
|
||||
|
@ -27,16 +27,17 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidSlf4jConfig;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidWallConfigUtil;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Druid数据源创建器
|
||||
*
|
||||
@ -46,115 +47,115 @@ import org.springframework.util.StringUtils;
|
||||
@Data
|
||||
public class DruidDataSourceCreator {
|
||||
|
||||
private DruidConfig druidConfig;
|
||||
private DruidConfig druidConfig;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ApplicationContext applicationContext;
|
||||
@Autowired(required = false)
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public DruidDataSourceCreator(DruidConfig druidConfig) {
|
||||
this.druidConfig = druidConfig;
|
||||
}
|
||||
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
dataSource.setUsername(dataSourceProperty.getUsername());
|
||||
dataSource.setPassword(dataSourceProperty.getPassword());
|
||||
dataSource.setUrl(dataSourceProperty.getUrl());
|
||||
dataSource.setDriverClassName(dataSourceProperty.getDriverClassName());
|
||||
dataSource.setName(dataSourceProperty.getPoolName());
|
||||
DruidConfig config = dataSourceProperty.getDruid();
|
||||
Properties properties = config.toProperties(druidConfig);
|
||||
String filters = properties.getProperty("druid.filters");
|
||||
List<Filter> proxyFilters = new ArrayList<>(2);
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("stat")) {
|
||||
StatFilter statFilter = new StatFilter();
|
||||
statFilter.configFromProperties(properties);
|
||||
proxyFilters.add(statFilter);
|
||||
}
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("wall")) {
|
||||
WallConfig wallConfig = DruidWallConfigUtil.toWallConfig(dataSourceProperty.getDruid().getWall(), druidConfig.getWall());
|
||||
WallFilter wallFilter = new WallFilter();
|
||||
wallFilter.setConfig(wallConfig);
|
||||
proxyFilters.add(wallFilter);
|
||||
}
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("slf4j")) {
|
||||
Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
|
||||
// 由于properties上面被用了,LogFilter不能使用configFromProperties方法,这里只能一个个set了。
|
||||
DruidSlf4jConfig slf4jConfig = druidConfig.getSlf4j();
|
||||
slf4jLogFilter.setStatementLogEnabled(slf4jConfig.getEnable());
|
||||
slf4jLogFilter.setStatementExecutableSqlLogEnable(slf4jConfig.getStatementExecutableSqlLogEnable());
|
||||
proxyFilters.add(slf4jLogFilter);
|
||||
public DruidDataSourceCreator(DruidConfig druidConfig) {
|
||||
this.druidConfig = druidConfig;
|
||||
}
|
||||
|
||||
if (this.applicationContext != null) {
|
||||
for (String filterId : druidConfig.getProxyFilters()) {
|
||||
proxyFilters.add(this.applicationContext.getBean(filterId, Filter.class));
|
||||
}
|
||||
}
|
||||
dataSource.setProxyFilters(proxyFilters);
|
||||
dataSource.configFromPropety(properties);
|
||||
//连接参数单独设置
|
||||
dataSource.setConnectProperties(config.getConnectionProperties());
|
||||
//设置druid内置properties不支持的的参数
|
||||
Boolean testOnReturn = config.getTestOnReturn() == null ? druidConfig.getTestOnReturn() : config.getTestOnReturn();
|
||||
if (testOnReturn != null && testOnReturn.equals(true)) {
|
||||
dataSource.setTestOnReturn(true);
|
||||
}
|
||||
Integer validationQueryTimeout =
|
||||
config.getValidationQueryTimeout() == null ? druidConfig.getValidationQueryTimeout() : config.getValidationQueryTimeout();
|
||||
if (validationQueryTimeout != null && !validationQueryTimeout.equals(-1)) {
|
||||
dataSource.setValidationQueryTimeout(validationQueryTimeout);
|
||||
}
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
dataSource.setUsername(dataSourceProperty.getUsername());
|
||||
dataSource.setPassword(dataSourceProperty.getPassword());
|
||||
dataSource.setUrl(dataSourceProperty.getUrl());
|
||||
dataSource.setDriverClassName(dataSourceProperty.getDriverClassName());
|
||||
dataSource.setName(dataSourceProperty.getPoolName());
|
||||
DruidConfig config = dataSourceProperty.getDruid();
|
||||
Properties properties = config.toProperties(druidConfig);
|
||||
String filters = properties.getProperty("druid.filters");
|
||||
List<Filter> proxyFilters = new ArrayList<>(2);
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("stat")) {
|
||||
StatFilter statFilter = new StatFilter();
|
||||
statFilter.configFromProperties(properties);
|
||||
proxyFilters.add(statFilter);
|
||||
}
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("wall")) {
|
||||
WallConfig wallConfig = DruidWallConfigUtil.toWallConfig(dataSourceProperty.getDruid().getWall(), druidConfig.getWall());
|
||||
WallFilter wallFilter = new WallFilter();
|
||||
wallFilter.setConfig(wallConfig);
|
||||
proxyFilters.add(wallFilter);
|
||||
}
|
||||
if (!StringUtils.isEmpty(filters) && filters.contains("slf4j")) {
|
||||
Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
|
||||
// 由于properties上面被用了,LogFilter不能使用configFromProperties方法,这里只能一个个set了。
|
||||
DruidSlf4jConfig slf4jConfig = druidConfig.getSlf4j();
|
||||
slf4jLogFilter.setStatementLogEnabled(slf4jConfig.getEnable());
|
||||
slf4jLogFilter.setStatementExecutableSqlLogEnable(slf4jConfig.getStatementExecutableSqlLogEnable());
|
||||
proxyFilters.add(slf4jLogFilter);
|
||||
}
|
||||
|
||||
Boolean sharePreparedStatements =
|
||||
config.getSharePreparedStatements() == null ? druidConfig.getSharePreparedStatements() : config.getSharePreparedStatements();
|
||||
if (sharePreparedStatements != null && sharePreparedStatements.equals(true)) {
|
||||
dataSource.setSharePreparedStatements(true);
|
||||
}
|
||||
Integer connectionErrorRetryAttempts =
|
||||
config.getConnectionErrorRetryAttempts() == null ? druidConfig.getConnectionErrorRetryAttempts()
|
||||
: config.getConnectionErrorRetryAttempts();
|
||||
if (connectionErrorRetryAttempts != null && !connectionErrorRetryAttempts.equals(1)) {
|
||||
dataSource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
|
||||
}
|
||||
Boolean breakAfterAcquireFailure =
|
||||
config.getBreakAfterAcquireFailure() == null ? druidConfig.getBreakAfterAcquireFailure() : config.getBreakAfterAcquireFailure();
|
||||
if (breakAfterAcquireFailure != null && breakAfterAcquireFailure.equals(true)) {
|
||||
dataSource.setBreakAfterAcquireFailure(true);
|
||||
}
|
||||
if (this.applicationContext != null) {
|
||||
for (String filterId : druidConfig.getProxyFilters()) {
|
||||
proxyFilters.add(this.applicationContext.getBean(filterId, Filter.class));
|
||||
}
|
||||
}
|
||||
dataSource.setProxyFilters(proxyFilters);
|
||||
dataSource.configFromPropety(properties);
|
||||
//连接参数单独设置
|
||||
dataSource.setConnectProperties(config.getConnectionProperties());
|
||||
//设置druid内置properties不支持的的参数
|
||||
Boolean testOnReturn = config.getTestOnReturn() == null ? druidConfig.getTestOnReturn() : config.getTestOnReturn();
|
||||
if (testOnReturn != null && testOnReturn.equals(true)) {
|
||||
dataSource.setTestOnReturn(true);
|
||||
}
|
||||
Integer validationQueryTimeout =
|
||||
config.getValidationQueryTimeout() == null ? druidConfig.getValidationQueryTimeout() : config.getValidationQueryTimeout();
|
||||
if (validationQueryTimeout != null && !validationQueryTimeout.equals(-1)) {
|
||||
dataSource.setValidationQueryTimeout(validationQueryTimeout);
|
||||
}
|
||||
|
||||
Integer timeout = config.getRemoveAbandonedTimeoutMillis() == null ? druidConfig.getRemoveAbandonedTimeoutMillis()
|
||||
: config.getRemoveAbandonedTimeoutMillis();
|
||||
if (timeout != null) {
|
||||
dataSource.setRemoveAbandonedTimeout(timeout);
|
||||
}
|
||||
Boolean sharePreparedStatements =
|
||||
config.getSharePreparedStatements() == null ? druidConfig.getSharePreparedStatements() : config.getSharePreparedStatements();
|
||||
if (sharePreparedStatements != null && sharePreparedStatements.equals(true)) {
|
||||
dataSource.setSharePreparedStatements(true);
|
||||
}
|
||||
Integer connectionErrorRetryAttempts =
|
||||
config.getConnectionErrorRetryAttempts() == null ? druidConfig.getConnectionErrorRetryAttempts()
|
||||
: config.getConnectionErrorRetryAttempts();
|
||||
if (connectionErrorRetryAttempts != null && !connectionErrorRetryAttempts.equals(1)) {
|
||||
dataSource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
|
||||
}
|
||||
Boolean breakAfterAcquireFailure =
|
||||
config.getBreakAfterAcquireFailure() == null ? druidConfig.getBreakAfterAcquireFailure() : config.getBreakAfterAcquireFailure();
|
||||
if (breakAfterAcquireFailure != null && breakAfterAcquireFailure.equals(true)) {
|
||||
dataSource.setBreakAfterAcquireFailure(true);
|
||||
}
|
||||
|
||||
Boolean abandoned = config.getRemoveAbandoned() == null ? druidConfig.getRemoveAbandoned() : config.getRemoveAbandoned();
|
||||
if (abandoned != null) {
|
||||
dataSource.setRemoveAbandoned(abandoned);
|
||||
}
|
||||
Integer timeout = config.getRemoveAbandonedTimeoutMillis() == null ? druidConfig.getRemoveAbandonedTimeoutMillis()
|
||||
: config.getRemoveAbandonedTimeoutMillis();
|
||||
if (timeout != null) {
|
||||
dataSource.setRemoveAbandonedTimeout(timeout);
|
||||
}
|
||||
|
||||
Boolean logAbandoned = config.getLogAbandoned() == null ? druidConfig.getLogAbandoned() : config.getLogAbandoned();
|
||||
if (logAbandoned != null) {
|
||||
dataSource.setLogAbandoned(logAbandoned);
|
||||
}
|
||||
Boolean abandoned = config.getRemoveAbandoned() == null ? druidConfig.getRemoveAbandoned() : config.getRemoveAbandoned();
|
||||
if (abandoned != null) {
|
||||
dataSource.setRemoveAbandoned(abandoned);
|
||||
}
|
||||
|
||||
Integer queryTimeOut = config.getQueryTimeout() == null ? druidConfig.getQueryTimeout() : config.getQueryTimeout();
|
||||
if (queryTimeOut != null) {
|
||||
dataSource.setQueryTimeout(queryTimeOut);
|
||||
}
|
||||
Boolean logAbandoned = config.getLogAbandoned() == null ? druidConfig.getLogAbandoned() : config.getLogAbandoned();
|
||||
if (logAbandoned != null) {
|
||||
dataSource.setLogAbandoned(logAbandoned);
|
||||
}
|
||||
|
||||
Integer transactionQueryTimeout =
|
||||
config.getTransactionQueryTimeout() == null ? druidConfig.getTransactionQueryTimeout() : config.getTransactionQueryTimeout();
|
||||
if (transactionQueryTimeout != null) {
|
||||
dataSource.setTransactionQueryTimeout(transactionQueryTimeout);
|
||||
}
|
||||
Integer queryTimeOut = config.getQueryTimeout() == null ? druidConfig.getQueryTimeout() : config.getQueryTimeout();
|
||||
if (queryTimeOut != null) {
|
||||
dataSource.setQueryTimeout(queryTimeOut);
|
||||
}
|
||||
|
||||
try {
|
||||
dataSource.init();
|
||||
} catch (SQLException e) {
|
||||
throw new ErrorCreateDataSourceException("druid create error", e);
|
||||
Integer transactionQueryTimeout =
|
||||
config.getTransactionQueryTimeout() == null ? druidConfig.getTransactionQueryTimeout() : config.getTransactionQueryTimeout();
|
||||
if (transactionQueryTimeout != null) {
|
||||
dataSource.setTransactionQueryTimeout(transactionQueryTimeout);
|
||||
}
|
||||
|
||||
try {
|
||||
dataSource.init();
|
||||
} catch (SQLException e) {
|
||||
throw new ErrorCreateDataSourceException("druid create error", e);
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,11 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCpConfig;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Hikari数据源创建器
|
||||
*
|
||||
@ -34,15 +35,15 @@ import lombok.Data;
|
||||
@AllArgsConstructor
|
||||
public class HikariDataSourceCreator {
|
||||
|
||||
private HikariCpConfig hikariCpConfig;
|
||||
private HikariCpConfig hikariCpConfig;
|
||||
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
HikariConfig config = dataSourceProperty.getHikari().toHikariConfig(hikariCpConfig);
|
||||
config.setUsername(dataSourceProperty.getUsername());
|
||||
config.setPassword(dataSourceProperty.getPassword());
|
||||
config.setJdbcUrl(dataSourceProperty.getUrl());
|
||||
config.setDriverClassName(dataSourceProperty.getDriverClassName());
|
||||
config.setPoolName(dataSourceProperty.getPoolName());
|
||||
return new HikariDataSource(config);
|
||||
}
|
||||
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
|
||||
HikariConfig config = dataSourceProperty.getHikari().toHikariConfig(hikariCpConfig);
|
||||
config.setUsername(dataSourceProperty.getUsername());
|
||||
config.setPassword(dataSourceProperty.getPassword());
|
||||
config.setJdbcUrl(dataSourceProperty.getUrl());
|
||||
config.setDriverClassName(dataSourceProperty.getDriverClassName());
|
||||
config.setPoolName(dataSourceProperty.getPoolName());
|
||||
return new HikariDataSource(config);
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,10 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.creator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* JNDI数据源创建器
|
||||
*
|
||||
@ -27,16 +28,16 @@ import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
|
||||
*/
|
||||
public class JndiDataSourceCreator {
|
||||
|
||||
private static final JndiDataSourceLookup LOOKUP = new JndiDataSourceLookup();
|
||||
private static final JndiDataSourceLookup LOOKUP = new JndiDataSourceLookup();
|
||||
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param name 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(String name) {
|
||||
return LOOKUP.getDataSource(name);
|
||||
}
|
||||
/**
|
||||
* 创建基础数据源
|
||||
*
|
||||
* @param name 数据源参数
|
||||
* @return 数据源
|
||||
*/
|
||||
public DataSource createDataSource(String name) {
|
||||
return LOOKUP.getDataSource(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,11 +24,11 @@ package com.baomidou.dynamic.datasource.exception;
|
||||
*/
|
||||
public class ErrorCreateDataSourceException extends RuntimeException {
|
||||
|
||||
public ErrorCreateDataSourceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public ErrorCreateDataSourceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ErrorCreateDataSourceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public ErrorCreateDataSourceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ExpressionMatcher implements Matcher {
|
||||
|
||||
private String expression;
|
||||
private String expression;
|
||||
|
||||
private String ds;
|
||||
private String ds;
|
||||
}
|
@ -27,8 +27,8 @@ import lombok.Data;
|
||||
@Data
|
||||
public class RegexMatcher implements Matcher {
|
||||
|
||||
private String pattern;
|
||||
private String pattern;
|
||||
|
||||
private String ds;
|
||||
private String ds;
|
||||
}
|
||||
|
||||
|
@ -20,21 +20,18 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSour
|
||||
import com.baomidou.dynamic.datasource.support.DbHealthIndicator;
|
||||
import com.baomidou.dynamic.datasource.support.DdConstants;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import java.util.Properties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlCommandType;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.plugin.Intercepts;
|
||||
import org.apache.ibatis.plugin.Invocation;
|
||||
import org.apache.ibatis.plugin.Plugin;
|
||||
import org.apache.ibatis.plugin.Signature;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Master-slave Separation Plugin with mybatis
|
||||
*
|
||||
@ -42,61 +39,61 @@ import org.springframework.util.StringUtils;
|
||||
* @since 2.5.1
|
||||
*/
|
||||
@Intercepts({
|
||||
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
||||
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
|
||||
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
||||
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
|
||||
@Slf4j
|
||||
public class MasterSlaveAutoRoutingPlugin implements Interceptor {
|
||||
|
||||
@Autowired
|
||||
private DynamicDataSourceProperties properties;
|
||||
@Autowired
|
||||
private DynamicDataSourceProperties properties;
|
||||
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
Object[] args = invocation.getArgs();
|
||||
MappedStatement ms = (MappedStatement) args[0];
|
||||
boolean empty = true;
|
||||
try {
|
||||
empty = StringUtils.isEmpty(DynamicDataSourceContextHolder.peek());
|
||||
if (empty) {
|
||||
DynamicDataSourceContextHolder.push(getDataSource(ms));
|
||||
}
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
if (empty) {
|
||||
DynamicDataSourceContextHolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取动态数据源名称,重写注入 DbHealthIndicator 支持数据源健康状况判断选择
|
||||
*
|
||||
* @param mappedStatement mybatis MappedStatement
|
||||
* @return 获取真实的数据源名称
|
||||
*/
|
||||
public String getDataSource(MappedStatement mappedStatement) {
|
||||
String slave = DdConstants.SLAVE;
|
||||
if (properties.isHealth()) {
|
||||
/*
|
||||
* 根据从库健康状况,判断是否切到主库
|
||||
*/
|
||||
boolean health = DbHealthIndicator.getDbHealth(DdConstants.SLAVE);
|
||||
if (!health) {
|
||||
health = DbHealthIndicator.getDbHealth(DdConstants.MASTER);
|
||||
if (health) {
|
||||
slave = DdConstants.MASTER;
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
Object[] args = invocation.getArgs();
|
||||
MappedStatement ms = (MappedStatement) args[0];
|
||||
boolean empty = true;
|
||||
try {
|
||||
empty = StringUtils.isEmpty(DynamicDataSourceContextHolder.peek());
|
||||
if (empty) {
|
||||
DynamicDataSourceContextHolder.push(getDataSource(ms));
|
||||
}
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
if (empty) {
|
||||
DynamicDataSourceContextHolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SqlCommandType.SELECT == mappedStatement.getSqlCommandType() ? slave : DdConstants.MASTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object plugin(Object target) {
|
||||
return target instanceof Executor ? Plugin.wrap(target, this) : target;
|
||||
}
|
||||
/**
|
||||
* 获取动态数据源名称,重写注入 DbHealthIndicator 支持数据源健康状况判断选择
|
||||
*
|
||||
* @param mappedStatement mybatis MappedStatement
|
||||
* @return 获取真实的数据源名称
|
||||
*/
|
||||
public String getDataSource(MappedStatement mappedStatement) {
|
||||
String slave = DdConstants.SLAVE;
|
||||
if (properties.isHealth()) {
|
||||
/*
|
||||
* 根据从库健康状况,判断是否切到主库
|
||||
*/
|
||||
boolean health = DbHealthIndicator.getDbHealth(DdConstants.SLAVE);
|
||||
if (!health) {
|
||||
health = DbHealthIndicator.getDbHealth(DdConstants.MASTER);
|
||||
if (health) {
|
||||
slave = DdConstants.MASTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SqlCommandType.SELECT == mappedStatement.getSqlCommandType() ? slave : DdConstants.MASTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
}
|
||||
@Override
|
||||
public Object plugin(Object target) {
|
||||
return target instanceof Executor ? Plugin.wrap(target, this) : target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
}
|
||||
}
|
||||
|
@ -16,30 +16,31 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.processor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class DsHeaderProcessor extends DsProcessor {
|
||||
|
||||
/**
|
||||
* header prefix
|
||||
*/
|
||||
private static final String HEADER_PREFIX = "#header";
|
||||
/**
|
||||
* header prefix
|
||||
*/
|
||||
private static final String HEADER_PREFIX = "#header";
|
||||
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return key.startsWith(HEADER_PREFIX);
|
||||
}
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return key.startsWith(HEADER_PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
return request.getHeader(key.substring(8));
|
||||
}
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
return request.getHeader(key.substring(8));
|
||||
}
|
||||
}
|
||||
|
@ -24,51 +24,51 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
*/
|
||||
public abstract class DsProcessor {
|
||||
|
||||
private DsProcessor nextProcessor;
|
||||
private DsProcessor nextProcessor;
|
||||
|
||||
public void setNextProcessor(DsProcessor dsProcessor) {
|
||||
this.nextProcessor = dsProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象匹配条件 匹配才会走当前执行器否则走下一级执行器
|
||||
*
|
||||
* @param key DS注解里的内容
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public abstract boolean matches(String key);
|
||||
|
||||
/**
|
||||
* 决定数据源
|
||||
* <pre>
|
||||
* 调用底层doDetermineDatasource,
|
||||
* 如果返回的是null则继续执行下一个,否则直接返回
|
||||
* </pre>
|
||||
*
|
||||
* @param invocation 方法执行信息
|
||||
* @param key DS注解里的内容
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public String determineDatasource(MethodInvocation invocation, String key) {
|
||||
if (matches(key)) {
|
||||
String datasource = doDetermineDatasource(invocation, key);
|
||||
if (datasource == null && nextProcessor != null) {
|
||||
return nextProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
return datasource;
|
||||
public void setNextProcessor(DsProcessor dsProcessor) {
|
||||
this.nextProcessor = dsProcessor;
|
||||
}
|
||||
if (nextProcessor != null) {
|
||||
return nextProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象最终决定数据源
|
||||
*
|
||||
* @param invocation 方法执行信息
|
||||
* @param key DS注解里的内容
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public abstract String doDetermineDatasource(MethodInvocation invocation, String key);
|
||||
/**
|
||||
* 抽象匹配条件 匹配才会走当前执行器否则走下一级执行器
|
||||
*
|
||||
* @param key DS注解里的内容
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public abstract boolean matches(String key);
|
||||
|
||||
/**
|
||||
* 决定数据源
|
||||
* <pre>
|
||||
* 调用底层doDetermineDatasource,
|
||||
* 如果返回的是null则继续执行下一个,否则直接返回
|
||||
* </pre>
|
||||
*
|
||||
* @param invocation 方法执行信息
|
||||
* @param key DS注解里的内容
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public String determineDatasource(MethodInvocation invocation, String key) {
|
||||
if (matches(key)) {
|
||||
String datasource = doDetermineDatasource(invocation, key);
|
||||
if (datasource == null && nextProcessor != null) {
|
||||
return nextProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
return datasource;
|
||||
}
|
||||
if (nextProcessor != null) {
|
||||
return nextProcessor.determineDatasource(invocation, key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象最终决定数据源
|
||||
*
|
||||
* @param invocation 方法执行信息
|
||||
* @param key DS注解里的内容
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public abstract String doDetermineDatasource(MethodInvocation invocation, String key);
|
||||
}
|
||||
|
@ -16,30 +16,31 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.processor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class DsSessionProcessor extends DsProcessor {
|
||||
|
||||
/**
|
||||
* session开头
|
||||
*/
|
||||
private static final String SESSION_PREFIX = "#session";
|
||||
/**
|
||||
* session开头
|
||||
*/
|
||||
private static final String SESSION_PREFIX = "#session";
|
||||
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return key.startsWith(SESSION_PREFIX);
|
||||
}
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return key.startsWith(SESSION_PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
return request.getSession().getAttribute(key.substring(9)).toString();
|
||||
}
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
return request.getSession().getAttribute(key.substring(9)).toString();
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.processor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.context.expression.MethodBasedEvaluationContext;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
@ -26,44 +25,45 @@ import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class DsSpelExpressionProcessor extends DsProcessor {
|
||||
|
||||
/**
|
||||
* 参数发现器
|
||||
*/
|
||||
private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
|
||||
/**
|
||||
* Express语法解析器
|
||||
*/
|
||||
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
||||
/**
|
||||
* 参数发现器
|
||||
*/
|
||||
private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
|
||||
/**
|
||||
* Express语法解析器
|
||||
*/
|
||||
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
||||
/**
|
||||
* 解析上下文的模板
|
||||
* 对于默认不设置的情况下,从参数中取值的方式 #param1
|
||||
* 设置指定模板 ParserContext.TEMPLATE_EXPRESSION 后的取值方式: #{#param1}
|
||||
* issues: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/issues/199
|
||||
*/
|
||||
private ParserContext parserContext = null;
|
||||
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean matches(String key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析上下文的模板
|
||||
* 对于默认不设置的情况下,从参数中取值的方式 #param1
|
||||
* 设置指定模板 ParserContext.TEMPLATE_EXPRESSION 后的取值方式: #{#param1}
|
||||
* issues: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/issues/199
|
||||
*/
|
||||
private ParserContext parserContext = null;
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
Method method = invocation.getMethod();
|
||||
Object[] arguments = invocation.getArguments();
|
||||
EvaluationContext context = new MethodBasedEvaluationContext(null, method, arguments, NAME_DISCOVERER);
|
||||
final Object value = PARSER.parseExpression(key, parserContext).getValue(context);
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doDetermineDatasource(MethodInvocation invocation, String key) {
|
||||
Method method = invocation.getMethod();
|
||||
Object[] arguments = invocation.getArguments();
|
||||
EvaluationContext context = new MethodBasedEvaluationContext(null, method, arguments, NAME_DISCOVERER);
|
||||
final Object value = PARSER.parseExpression(key,parserContext).getValue(context);
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
public void setParserContext(ParserContext parserContext) {
|
||||
this.parserContext = parserContext;
|
||||
}
|
||||
public void setParserContext(ParserContext parserContext) {
|
||||
this.parserContext = parserContext;
|
||||
}
|
||||
}
|
||||
|
@ -18,31 +18,32 @@ package com.baomidou.dynamic.datasource.provider;
|
||||
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractDataSourceProvider implements DynamicDataSourceProvider {
|
||||
|
||||
@Autowired
|
||||
private DataSourceCreator dataSourceCreator;
|
||||
@Autowired
|
||||
private DataSourceCreator dataSourceCreator;
|
||||
|
||||
protected Map<String, DataSource> createDataSourceMap(
|
||||
Map<String, DataSourceProperty> dataSourcePropertiesMap) {
|
||||
Map<String, DataSource> dataSourceMap = new HashMap<>(dataSourcePropertiesMap.size() * 2);
|
||||
for (Map.Entry<String, DataSourceProperty> item : dataSourcePropertiesMap.entrySet()) {
|
||||
DataSourceProperty dataSourceProperty = item.getValue();
|
||||
String pollName = dataSourceProperty.getPoolName();
|
||||
if (pollName == null || "".equals(pollName)) {
|
||||
pollName = item.getKey();
|
||||
}
|
||||
dataSourceProperty.setPoolName(pollName);
|
||||
dataSourceMap.put(pollName, dataSourceCreator.createDataSource(dataSourceProperty));
|
||||
protected Map<String, DataSource> createDataSourceMap(
|
||||
Map<String, DataSourceProperty> dataSourcePropertiesMap) {
|
||||
Map<String, DataSource> dataSourceMap = new HashMap<>(dataSourcePropertiesMap.size() * 2);
|
||||
for (Map.Entry<String, DataSourceProperty> item : dataSourcePropertiesMap.entrySet()) {
|
||||
DataSourceProperty dataSourceProperty = item.getValue();
|
||||
String pollName = dataSourceProperty.getPoolName();
|
||||
if (pollName == null || "".equals(pollName)) {
|
||||
pollName = item.getKey();
|
||||
}
|
||||
dataSourceProperty.setPoolName(pollName);
|
||||
dataSourceMap.put(pollName, dataSourceCreator.createDataSource(dataSourceProperty));
|
||||
}
|
||||
return dataSourceMap;
|
||||
}
|
||||
return dataSourceMap;
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,15 @@
|
||||
package com.baomidou.dynamic.datasource.provider;
|
||||
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
|
||||
/**
|
||||
* JDBC数据源提供者(抽象)
|
||||
@ -35,58 +36,58 @@ import org.springframework.jdbc.support.JdbcUtils;
|
||||
@Slf4j
|
||||
public abstract class AbstractJdbcDataSourceProvider extends AbstractDataSourceProvider implements DynamicDataSourceProvider {
|
||||
|
||||
/**
|
||||
* JDBC driver
|
||||
*/
|
||||
private String driverClassName;
|
||||
/**
|
||||
* JDBC url 地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* JDBC 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* JDBC 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* JDBC driver
|
||||
*/
|
||||
private String driverClassName;
|
||||
/**
|
||||
* JDBC url 地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* JDBC 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* JDBC 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
public AbstractJdbcDataSourceProvider(String driverClassName, String url, String username, String password) {
|
||||
this.driverClassName = driverClassName;
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, DataSource> loadDataSources() {
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
try {
|
||||
Class.forName(driverClassName);
|
||||
log.info("成功加载数据库驱动程序");
|
||||
conn = DriverManager.getConnection(url, username, password);
|
||||
log.info("成功获取数据库连接");
|
||||
stmt = conn.createStatement();
|
||||
Map<String, DataSourceProperty> dataSourcePropertiesMap = executeStmt(stmt);
|
||||
return createDataSourceMap(dataSourcePropertiesMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
JdbcUtils.closeConnection(conn);
|
||||
JdbcUtils.closeStatement(stmt);
|
||||
public AbstractJdbcDataSourceProvider(String driverClassName, String url, String username, String password) {
|
||||
this.driverClassName = driverClassName;
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句获得数据源参数
|
||||
*
|
||||
* @param statement 语句
|
||||
* @return 数据源参数
|
||||
* @throws SQLException sql异常
|
||||
*/
|
||||
protected abstract Map<String, DataSourceProperty> executeStmt(Statement statement)
|
||||
throws SQLException;
|
||||
@Override
|
||||
public Map<String, DataSource> loadDataSources() {
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
try {
|
||||
Class.forName(driverClassName);
|
||||
log.info("成功加载数据库驱动程序");
|
||||
conn = DriverManager.getConnection(url, username, password);
|
||||
log.info("成功获取数据库连接");
|
||||
stmt = conn.createStatement();
|
||||
Map<String, DataSourceProperty> dataSourcePropertiesMap = executeStmt(stmt);
|
||||
return createDataSourceMap(dataSourcePropertiesMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
JdbcUtils.closeConnection(conn);
|
||||
JdbcUtils.closeStatement(stmt);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行语句获得数据源参数
|
||||
*
|
||||
* @param statement 语句
|
||||
* @return 数据源参数
|
||||
* @throws SQLException sql异常
|
||||
*/
|
||||
protected abstract Map<String, DataSourceProperty> executeStmt(Statement statement)
|
||||
throws SQLException;
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.provider;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 多数据源加载接口,默认的实现为从yml信息中加载所有数据源 你可以自己实现从其他地方加载所有数据源
|
||||
@ -29,10 +29,10 @@ import javax.sql.DataSource;
|
||||
*/
|
||||
public interface DynamicDataSourceProvider {
|
||||
|
||||
/**
|
||||
* 加载所有数据源
|
||||
*
|
||||
* @return 所有数据源,key为数据源名称
|
||||
*/
|
||||
Map<String, DataSource> loadDataSources();
|
||||
/**
|
||||
* 加载所有数据源
|
||||
*
|
||||
* @return 所有数据源,key为数据源名称
|
||||
*/
|
||||
Map<String, DataSource> loadDataSources();
|
||||
}
|
||||
|
@ -17,11 +17,12 @@
|
||||
package com.baomidou.dynamic.datasource.provider;
|
||||
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* YML数据源提供者
|
||||
*
|
||||
@ -32,13 +33,13 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@AllArgsConstructor
|
||||
public class YmlDynamicDataSourceProvider extends AbstractDataSourceProvider implements DynamicDataSourceProvider {
|
||||
|
||||
/**
|
||||
* 所有数据源
|
||||
*/
|
||||
private Map<String, DataSourceProperty> dataSourcePropertiesMap;
|
||||
/**
|
||||
* 所有数据源
|
||||
*/
|
||||
private Map<String, DataSourceProperty> dataSourcePropertiesMap;
|
||||
|
||||
@Override
|
||||
public Map<String, DataSource> loadDataSources() {
|
||||
return createDataSourceMap(dataSourcePropertiesMap);
|
||||
}
|
||||
@Override
|
||||
public Map<String, DataSource> loadDataSources() {
|
||||
return createDataSourceMap(dataSourcePropertiesMap);
|
||||
}
|
||||
}
|
||||
|
@ -19,15 +19,16 @@ package com.baomidou.dynamic.datasource.spring.boot.autoconfigure;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCpConfig;
|
||||
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author TaoYu
|
||||
* @since 1.2.0
|
||||
@ -37,97 +38,97 @@ import org.springframework.util.StringUtils;
|
||||
@Accessors(chain = true)
|
||||
public class DataSourceProperty {
|
||||
|
||||
/**
|
||||
* 加密正则
|
||||
*/
|
||||
private static final Pattern ENC_PATTERN = Pattern.compile("^ENC\\((.*)\\)$");
|
||||
/**
|
||||
* 加密正则
|
||||
*/
|
||||
private static final Pattern ENC_PATTERN = Pattern.compile("^ENC\\((.*)\\)$");
|
||||
|
||||
/**
|
||||
* 连接池名称(只是一个名称标识)</br> 默认是配置文件上的名称
|
||||
*/
|
||||
private String poolName;
|
||||
/**
|
||||
* 连接池类型,如果不设置自动查找 Druid > HikariCp
|
||||
*/
|
||||
private Class<? extends DataSource> type;
|
||||
/**
|
||||
* JDBC driver
|
||||
*/
|
||||
private String driverClassName;
|
||||
/**
|
||||
* JDBC url 地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* JDBC 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* JDBC 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* jndi数据源名称(设置即表示启用)
|
||||
*/
|
||||
private String jndiName;
|
||||
/**
|
||||
* 自动运行的建表脚本
|
||||
*/
|
||||
private String schema;
|
||||
/**
|
||||
* 自动运行的数据脚本
|
||||
*/
|
||||
private String data;
|
||||
/**
|
||||
* 错误是否继续 默认 true
|
||||
*/
|
||||
private boolean continueOnError = true;
|
||||
/**
|
||||
* 分隔符 默认 ;
|
||||
*/
|
||||
private String separator = ";";
|
||||
/**
|
||||
* Druid参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private DruidConfig druid = new DruidConfig();
|
||||
/**
|
||||
* HikariCp参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private HikariCpConfig hikari = new HikariCpConfig();
|
||||
/**
|
||||
* 连接池名称(只是一个名称标识)</br> 默认是配置文件上的名称
|
||||
*/
|
||||
private String poolName;
|
||||
/**
|
||||
* 连接池类型,如果不设置自动查找 Druid > HikariCp
|
||||
*/
|
||||
private Class<? extends DataSource> type;
|
||||
/**
|
||||
* JDBC driver
|
||||
*/
|
||||
private String driverClassName;
|
||||
/**
|
||||
* JDBC url 地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* JDBC 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* JDBC 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* jndi数据源名称(设置即表示启用)
|
||||
*/
|
||||
private String jndiName;
|
||||
/**
|
||||
* 自动运行的建表脚本
|
||||
*/
|
||||
private String schema;
|
||||
/**
|
||||
* 自动运行的数据脚本
|
||||
*/
|
||||
private String data;
|
||||
/**
|
||||
* 错误是否继续 默认 true
|
||||
*/
|
||||
private boolean continueOnError = true;
|
||||
/**
|
||||
* 分隔符 默认 ;
|
||||
*/
|
||||
private String separator = ";";
|
||||
/**
|
||||
* Druid参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private DruidConfig druid = new DruidConfig();
|
||||
/**
|
||||
* HikariCp参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private HikariCpConfig hikari = new HikariCpConfig();
|
||||
|
||||
/**
|
||||
* 解密公匙(如果未设置默认使用全局的)
|
||||
*/
|
||||
private String publicKey;
|
||||
/**
|
||||
* 解密公匙(如果未设置默认使用全局的)
|
||||
*/
|
||||
private String publicKey;
|
||||
|
||||
public String getUrl() {
|
||||
return decrypt(url);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return decrypt(username);
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return decrypt(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串解密
|
||||
*/
|
||||
private String decrypt(String cipherText) {
|
||||
if (StringUtils.hasText(cipherText)) {
|
||||
Matcher matcher = ENC_PATTERN.matcher(cipherText);
|
||||
if (matcher.find()) {
|
||||
try {
|
||||
return CryptoUtils.decrypt(publicKey, matcher.group(1));
|
||||
} catch (Exception e) {
|
||||
log.error("DynamicDataSourceProperties.decrypt error ", e);
|
||||
}
|
||||
}
|
||||
public String getUrl() {
|
||||
return decrypt(url);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return decrypt(username);
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return decrypt(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串解密
|
||||
*/
|
||||
private String decrypt(String cipherText) {
|
||||
if (StringUtils.hasText(cipherText)) {
|
||||
Matcher matcher = ENC_PATTERN.matcher(cipherText);
|
||||
if (matcher.find()) {
|
||||
try {
|
||||
return CryptoUtils.decrypt(publicKey, matcher.group(1));
|
||||
} catch (Exception e) {
|
||||
log.error("DynamicDataSourceProperties.decrypt error ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cipherText;
|
||||
}
|
||||
return cipherText;
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,6 @@ import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidDynamicDataSourceConfiguration;
|
||||
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
@ -43,7 +41,9 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.expression.ParserContext;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 动态数据源核心自动配置类
|
||||
@ -63,55 +63,55 @@ import org.springframework.expression.ParserContext;
|
||||
@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class DynamicDataSourceAutoConfiguration {
|
||||
|
||||
private final DynamicDataSourceProperties properties;
|
||||
private final DynamicDataSourceProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
|
||||
return new YmlDynamicDataSourceProvider(datasourceMap);
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
|
||||
return new YmlDynamicDataSourceProvider(datasourceMap);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
|
||||
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
|
||||
dataSource.setPrimary(properties.getPrimary());
|
||||
dataSource.setStrict(properties.getStrict());
|
||||
dataSource.setStrategy(properties.getStrategy());
|
||||
dataSource.setProvider(dynamicDataSourceProvider);
|
||||
dataSource.setP6spy(properties.getP6spy());
|
||||
dataSource.setSeata(properties.getSeata());
|
||||
return dataSource;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
|
||||
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
|
||||
dataSource.setPrimary(properties.getPrimary());
|
||||
dataSource.setStrict(properties.getStrict());
|
||||
dataSource.setStrategy(properties.getStrategy());
|
||||
dataSource.setProvider(dynamicDataSourceProvider);
|
||||
dataSource.setP6spy(properties.getP6spy());
|
||||
dataSource.setSeata(properties.getSeata());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
|
||||
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor();
|
||||
interceptor.setDsProcessor(dsProcessor);
|
||||
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
|
||||
advisor.setOrder(properties.getOrder());
|
||||
return advisor;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
|
||||
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor();
|
||||
interceptor.setDsProcessor(dsProcessor);
|
||||
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
|
||||
advisor.setOrder(properties.getOrder());
|
||||
return advisor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DsProcessor dsProcessor() {
|
||||
DsHeaderProcessor headerProcessor = new DsHeaderProcessor();
|
||||
DsSessionProcessor sessionProcessor = new DsSessionProcessor();
|
||||
DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
|
||||
headerProcessor.setNextProcessor(sessionProcessor);
|
||||
sessionProcessor.setNextProcessor(spelExpressionProcessor);
|
||||
return headerProcessor;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DsProcessor dsProcessor() {
|
||||
DsHeaderProcessor headerProcessor = new DsHeaderProcessor();
|
||||
DsSessionProcessor sessionProcessor = new DsSessionProcessor();
|
||||
DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
|
||||
headerProcessor.setNextProcessor(sessionProcessor);
|
||||
sessionProcessor.setNextProcessor(spelExpressionProcessor);
|
||||
return headerProcessor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(DynamicDataSourceConfigure.class)
|
||||
public DynamicDataSourceAdvisor dynamicAdvisor(DynamicDataSourceConfigure dynamicDataSourceConfigure, DsProcessor dsProcessor) {
|
||||
DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(dynamicDataSourceConfigure.getMatchers());
|
||||
advisor.setDsProcessor(dsProcessor);
|
||||
advisor.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
return advisor;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnBean(DynamicDataSourceConfigure.class)
|
||||
public DynamicDataSourceAdvisor dynamicAdvisor(DynamicDataSourceConfigure dynamicDataSourceConfigure, DsProcessor dsProcessor) {
|
||||
DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(dynamicDataSourceConfigure.getMatchers());
|
||||
advisor.setDsProcessor(dsProcessor);
|
||||
advisor.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
return advisor;
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,7 @@
|
||||
*/
|
||||
package com.baomidou.dynamic.datasource.spring.boot.autoconfigure;
|
||||
|
||||
import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.JndiDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.creator.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@ -34,41 +30,41 @@ import org.springframework.context.annotation.Configuration;
|
||||
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
|
||||
public class DynamicDataSourceCreatorAutoConfiguration {
|
||||
|
||||
private final DynamicDataSourceProperties properties;
|
||||
private final DynamicDataSourceProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataSourceCreator dataSourceCreator() {
|
||||
DataSourceCreator dataSourceCreator = new DataSourceCreator();
|
||||
dataSourceCreator.setBasicDataSourceCreator(basicDataSourceCreator());
|
||||
dataSourceCreator.setJndiDataSourceCreator(jndiDataSourceCreator());
|
||||
dataSourceCreator.setDruidDataSourceCreator(druidDataSourceCreator());
|
||||
dataSourceCreator.setHikariDataSourceCreator(hikariDataSourceCreator());
|
||||
dataSourceCreator.setGlobalPublicKey(properties.getPublicKey());
|
||||
return dataSourceCreator;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataSourceCreator dataSourceCreator() {
|
||||
DataSourceCreator dataSourceCreator = new DataSourceCreator();
|
||||
dataSourceCreator.setBasicDataSourceCreator(basicDataSourceCreator());
|
||||
dataSourceCreator.setJndiDataSourceCreator(jndiDataSourceCreator());
|
||||
dataSourceCreator.setDruidDataSourceCreator(druidDataSourceCreator());
|
||||
dataSourceCreator.setHikariDataSourceCreator(hikariDataSourceCreator());
|
||||
dataSourceCreator.setGlobalPublicKey(properties.getPublicKey());
|
||||
return dataSourceCreator;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BasicDataSourceCreator basicDataSourceCreator() {
|
||||
return new BasicDataSourceCreator();
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BasicDataSourceCreator basicDataSourceCreator() {
|
||||
return new BasicDataSourceCreator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public JndiDataSourceCreator jndiDataSourceCreator() {
|
||||
return new JndiDataSourceCreator();
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public JndiDataSourceCreator jndiDataSourceCreator() {
|
||||
return new JndiDataSourceCreator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DruidDataSourceCreator druidDataSourceCreator() {
|
||||
return new DruidDataSourceCreator(properties.getDruid());
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DruidDataSourceCreator druidDataSourceCreator() {
|
||||
return new DruidDataSourceCreator(properties.getDruid());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HikariDataSourceCreator hikariDataSourceCreator() {
|
||||
return new HikariDataSourceCreator(properties.getHikari());
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HikariDataSourceCreator hikariDataSourceCreator() {
|
||||
return new HikariDataSourceCreator(properties.getHikari());
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCp
|
||||
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
|
||||
import com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy;
|
||||
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -31,6 +29,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DynamicDataSourceProperties
|
||||
*
|
||||
@ -44,54 +45,54 @@ import org.springframework.core.Ordered;
|
||||
@ConfigurationProperties(prefix = DynamicDataSourceProperties.PREFIX)
|
||||
public class DynamicDataSourceProperties {
|
||||
|
||||
public static final String PREFIX = "spring.datasource.dynamic";
|
||||
public static final String HEALTH = PREFIX + ".health";
|
||||
public static final String PREFIX = "spring.datasource.dynamic";
|
||||
public static final String HEALTH = PREFIX + ".health";
|
||||
|
||||
/**
|
||||
* 必须设置默认的库,默认master
|
||||
*/
|
||||
private String primary = "master";
|
||||
/**
|
||||
* 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源
|
||||
*/
|
||||
private Boolean strict = false;
|
||||
/**
|
||||
* 是否使用p6spy输出,默认不输出
|
||||
*/
|
||||
private Boolean p6spy = false;
|
||||
/**
|
||||
* 是否使用seata,默认不使用
|
||||
*/
|
||||
private Boolean seata = false;
|
||||
/**
|
||||
* 是否使用 spring actuator 监控检查,默认不检查
|
||||
*/
|
||||
private boolean health = false;
|
||||
/**
|
||||
* 每一个数据源
|
||||
*/
|
||||
private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>();
|
||||
/**
|
||||
* 多数据源选择算法clazz,默认负载均衡算法
|
||||
*/
|
||||
private Class<? extends DynamicDataSourceStrategy> strategy = LoadBalanceDynamicDataSourceStrategy.class;
|
||||
/**
|
||||
* aop切面顺序,默认优先级最高
|
||||
*/
|
||||
private Integer order = Ordered.HIGHEST_PRECEDENCE;
|
||||
/**
|
||||
* Druid全局参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private DruidConfig druid = new DruidConfig();
|
||||
/**
|
||||
* HikariCp全局参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private HikariCpConfig hikari = new HikariCpConfig();
|
||||
/**
|
||||
* 必须设置默认的库,默认master
|
||||
*/
|
||||
private String primary = "master";
|
||||
/**
|
||||
* 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源
|
||||
*/
|
||||
private Boolean strict = false;
|
||||
/**
|
||||
* 是否使用p6spy输出,默认不输出
|
||||
*/
|
||||
private Boolean p6spy = false;
|
||||
/**
|
||||
* 是否使用seata,默认不使用
|
||||
*/
|
||||
private Boolean seata = false;
|
||||
/**
|
||||
* 是否使用 spring actuator 监控检查,默认不检查
|
||||
*/
|
||||
private boolean health = false;
|
||||
/**
|
||||
* 每一个数据源
|
||||
*/
|
||||
private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>();
|
||||
/**
|
||||
* 多数据源选择算法clazz,默认负载均衡算法
|
||||
*/
|
||||
private Class<? extends DynamicDataSourceStrategy> strategy = LoadBalanceDynamicDataSourceStrategy.class;
|
||||
/**
|
||||
* aop切面顺序,默认优先级最高
|
||||
*/
|
||||
private Integer order = Ordered.HIGHEST_PRECEDENCE;
|
||||
/**
|
||||
* Druid全局参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private DruidConfig druid = new DruidConfig();
|
||||
/**
|
||||
* HikariCp全局参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private HikariCpConfig hikari = new HikariCpConfig();
|
||||
|
||||
/**
|
||||
* 全局默认publicKey
|
||||
*/
|
||||
private String publicKey = CryptoUtils.DEFAULT_PUBLIC_KEY_STRING;
|
||||
/**
|
||||
* 全局默认publicKey
|
||||
*/
|
||||
private String publicKey = CryptoUtils.DEFAULT_PUBLIC_KEY_STRING;
|
||||
}
|
||||
|
@ -41,259 +41,259 @@ import static com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.Dr
|
||||
@Slf4j
|
||||
public class DruidConfig {
|
||||
|
||||
private Integer initialSize;
|
||||
private Integer maxActive;
|
||||
private Integer minIdle;
|
||||
private Integer maxWait;
|
||||
private Long timeBetweenEvictionRunsMillis;
|
||||
private Long timeBetweenLogStatsMillis;
|
||||
private Integer statSqlMaxSize;
|
||||
private Long minEvictableIdleTimeMillis;
|
||||
private Long maxEvictableIdleTimeMillis;
|
||||
private Boolean testWhileIdle;
|
||||
private Boolean testOnBorrow;
|
||||
private Boolean testOnReturn;
|
||||
private String validationQuery;
|
||||
private Integer validationQueryTimeout;
|
||||
private Boolean useGlobalDataSourceStat;
|
||||
private Boolean asyncInit;
|
||||
private String filters;
|
||||
private Boolean clearFiltersEnable;
|
||||
private Boolean resetStatEnable;
|
||||
private Integer notFullTimeoutRetryCount;
|
||||
private Integer maxWaitThreadCount;
|
||||
private Boolean failFast;
|
||||
private Long phyTimeoutMillis;
|
||||
private Boolean keepAlive;
|
||||
private Boolean poolPreparedStatements;
|
||||
private Boolean initVariants;
|
||||
private Boolean initGlobalVariants;
|
||||
private Boolean useUnfairLock;
|
||||
private Boolean killWhenSocketReadTimeout;
|
||||
private Properties connectionProperties;
|
||||
private Integer maxPoolPreparedStatementPerConnectionSize;
|
||||
private String initConnectionSqls;
|
||||
private Boolean sharePreparedStatements;
|
||||
private Integer connectionErrorRetryAttempts;
|
||||
private Boolean breakAfterAcquireFailure;
|
||||
private Boolean removeAbandoned;
|
||||
private Integer removeAbandonedTimeoutMillis;
|
||||
private Boolean logAbandoned;
|
||||
private Integer queryTimeout;
|
||||
private Integer transactionQueryTimeout;
|
||||
private String publicKey;
|
||||
private Integer initialSize;
|
||||
private Integer maxActive;
|
||||
private Integer minIdle;
|
||||
private Integer maxWait;
|
||||
private Long timeBetweenEvictionRunsMillis;
|
||||
private Long timeBetweenLogStatsMillis;
|
||||
private Integer statSqlMaxSize;
|
||||
private Long minEvictableIdleTimeMillis;
|
||||
private Long maxEvictableIdleTimeMillis;
|
||||
private Boolean testWhileIdle;
|
||||
private Boolean testOnBorrow;
|
||||
private Boolean testOnReturn;
|
||||
private String validationQuery;
|
||||
private Integer validationQueryTimeout;
|
||||
private Boolean useGlobalDataSourceStat;
|
||||
private Boolean asyncInit;
|
||||
private String filters;
|
||||
private Boolean clearFiltersEnable;
|
||||
private Boolean resetStatEnable;
|
||||
private Integer notFullTimeoutRetryCount;
|
||||
private Integer maxWaitThreadCount;
|
||||
private Boolean failFast;
|
||||
private Long phyTimeoutMillis;
|
||||
private Boolean keepAlive;
|
||||
private Boolean poolPreparedStatements;
|
||||
private Boolean initVariants;
|
||||
private Boolean initGlobalVariants;
|
||||
private Boolean useUnfairLock;
|
||||
private Boolean killWhenSocketReadTimeout;
|
||||
private Properties connectionProperties;
|
||||
private Integer maxPoolPreparedStatementPerConnectionSize;
|
||||
private String initConnectionSqls;
|
||||
private Boolean sharePreparedStatements;
|
||||
private Integer connectionErrorRetryAttempts;
|
||||
private Boolean breakAfterAcquireFailure;
|
||||
private Boolean removeAbandoned;
|
||||
private Integer removeAbandonedTimeoutMillis;
|
||||
private Boolean logAbandoned;
|
||||
private Integer queryTimeout;
|
||||
private Integer transactionQueryTimeout;
|
||||
private String publicKey;
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private DruidWallConfig wall = new DruidWallConfig();
|
||||
@NestedConfigurationProperty
|
||||
private DruidWallConfig wall = new DruidWallConfig();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private DruidStatConfig stat = new DruidStatConfig();
|
||||
@NestedConfigurationProperty
|
||||
private DruidStatConfig stat = new DruidStatConfig();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private DruidSlf4jConfig slf4j = new DruidSlf4jConfig();
|
||||
@NestedConfigurationProperty
|
||||
private DruidSlf4jConfig slf4j = new DruidSlf4jConfig();
|
||||
|
||||
private List<String> proxyFilters = new ArrayList<>();
|
||||
private List<String> proxyFilters = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 根据全局配置和本地配置结合转换为Properties
|
||||
*
|
||||
* @param g 全局配置
|
||||
* @return Druid配置
|
||||
*/
|
||||
public Properties toProperties(DruidConfig g) {
|
||||
Properties properties = new Properties();
|
||||
Integer initialSize = this.initialSize == null ? g.getInitialSize() : this.initialSize;
|
||||
if (initialSize != null && !initialSize.equals(DEFAULT_INITIAL_SIZE)) {
|
||||
properties.setProperty(INITIAL_SIZE, String.valueOf(initialSize));
|
||||
/**
|
||||
* 根据全局配置和本地配置结合转换为Properties
|
||||
*
|
||||
* @param g 全局配置
|
||||
* @return Druid配置
|
||||
*/
|
||||
public Properties toProperties(DruidConfig g) {
|
||||
Properties properties = new Properties();
|
||||
Integer initialSize = this.initialSize == null ? g.getInitialSize() : this.initialSize;
|
||||
if (initialSize != null && !initialSize.equals(DEFAULT_INITIAL_SIZE)) {
|
||||
properties.setProperty(INITIAL_SIZE, String.valueOf(initialSize));
|
||||
}
|
||||
|
||||
Integer maxActive = this.maxActive == null ? g.getMaxActive() : this.maxActive;
|
||||
if (maxActive != null && !maxActive.equals(DEFAULT_MAX_WAIT)) {
|
||||
properties.setProperty(MAX_ACTIVE, String.valueOf(maxActive));
|
||||
}
|
||||
|
||||
Integer minIdle = this.minIdle == null ? g.getMinIdle() : this.minIdle;
|
||||
if (minIdle != null && !minIdle.equals(DEFAULT_MIN_IDLE)) {
|
||||
properties.setProperty(MIN_IDLE, String.valueOf(minIdle));
|
||||
}
|
||||
|
||||
Integer maxWait = this.maxWait == null ? g.getMaxWait() : this.maxWait;
|
||||
if (maxWait != null && !maxWait.equals(DEFAULT_MAX_WAIT)) {
|
||||
properties.setProperty(MAX_WAIT, String.valueOf(maxWait));
|
||||
}
|
||||
|
||||
Long timeBetweenEvictionRunsMillis =
|
||||
this.timeBetweenEvictionRunsMillis == null ? g.getTimeBetweenEvictionRunsMillis() : this.timeBetweenEvictionRunsMillis;
|
||||
if (timeBetweenEvictionRunsMillis != null && !timeBetweenEvictionRunsMillis.equals(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS)) {
|
||||
properties.setProperty(TIME_BETWEEN_EVICTION_RUNS_MILLIS, String.valueOf(timeBetweenEvictionRunsMillis));
|
||||
}
|
||||
|
||||
Long timeBetweenLogStatsMillis =
|
||||
this.timeBetweenLogStatsMillis == null ? g.getTimeBetweenLogStatsMillis() : this.timeBetweenLogStatsMillis;
|
||||
if (timeBetweenLogStatsMillis != null && timeBetweenLogStatsMillis > 0) {
|
||||
properties.setProperty(TIME_BETWEEN_LOG_STATS_MILLIS, String.valueOf(timeBetweenLogStatsMillis));
|
||||
}
|
||||
|
||||
Long minEvictableIdleTimeMillis =
|
||||
this.minEvictableIdleTimeMillis == null ? g.getMinEvictableIdleTimeMillis() : this.minEvictableIdleTimeMillis;
|
||||
if (minEvictableIdleTimeMillis != null && !minEvictableIdleTimeMillis.equals(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS)) {
|
||||
properties.setProperty(MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(minEvictableIdleTimeMillis));
|
||||
}
|
||||
|
||||
Long maxEvictableIdleTimeMillis =
|
||||
this.maxEvictableIdleTimeMillis == null ? g.getMaxEvictableIdleTimeMillis() : this.maxEvictableIdleTimeMillis;
|
||||
if (maxEvictableIdleTimeMillis != null && !maxEvictableIdleTimeMillis.equals(DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS)) {
|
||||
properties.setProperty(MAX_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(maxEvictableIdleTimeMillis));
|
||||
}
|
||||
|
||||
Boolean testWhileIdle = this.testWhileIdle == null ? g.getTestWhileIdle() : this.testWhileIdle;
|
||||
if (testWhileIdle != null && !testWhileIdle.equals(DEFAULT_WHILE_IDLE)) {
|
||||
properties.setProperty(TEST_WHILE_IDLE, "false");
|
||||
}
|
||||
|
||||
Boolean testOnBorrow = this.testOnBorrow == null ? g.getTestOnBorrow() : this.testOnBorrow;
|
||||
if (testOnBorrow != null && !testOnBorrow.equals(DEFAULT_TEST_ON_BORROW)) {
|
||||
properties.setProperty(TEST_ON_BORROW, "true");
|
||||
}
|
||||
|
||||
String validationQuery = this.validationQuery == null ? g.getValidationQuery() : this.validationQuery;
|
||||
if (validationQuery != null && validationQuery.length() > 0) {
|
||||
properties.setProperty(VALIDATION_QUERY, validationQuery);
|
||||
}
|
||||
|
||||
Boolean useGlobalDataSourceStat = this.useGlobalDataSourceStat == null ? g.getUseGlobalDataSourceStat() : this.useGlobalDataSourceStat;
|
||||
if (useGlobalDataSourceStat != null && useGlobalDataSourceStat.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(USE_GLOBAL_DATA_SOURCE_STAT, "true");
|
||||
}
|
||||
|
||||
Boolean asyncInit = this.asyncInit == null ? g.getAsyncInit() : this.asyncInit;
|
||||
if (asyncInit != null && asyncInit.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(ASYNC_INIT, "true");
|
||||
}
|
||||
|
||||
//filters单独处理,默认了stat,wall
|
||||
String filters = this.filters == null ? g.getFilters() : this.filters;
|
||||
if (filters == null) {
|
||||
filters = "stat,wall";
|
||||
}
|
||||
if (publicKey != null && publicKey.length() > 0 && !filters.contains("config")) {
|
||||
filters += ",config";
|
||||
}
|
||||
properties.setProperty(FILTERS, filters);
|
||||
|
||||
Boolean clearFiltersEnable = this.clearFiltersEnable == null ? g.getClearFiltersEnable() : this.clearFiltersEnable;
|
||||
if (clearFiltersEnable != null && clearFiltersEnable.equals(Boolean.FALSE)) {
|
||||
properties.setProperty(CLEAR_FILTERS_ENABLE, "false");
|
||||
}
|
||||
|
||||
Boolean resetStatEnable = this.resetStatEnable == null ? g.getResetStatEnable() : this.resetStatEnable;
|
||||
if (resetStatEnable != null && resetStatEnable.equals(Boolean.FALSE)) {
|
||||
properties.setProperty(RESET_STAT_ENABLE, "false");
|
||||
}
|
||||
|
||||
Integer notFullTimeoutRetryCount =
|
||||
this.notFullTimeoutRetryCount == null ? g.getNotFullTimeoutRetryCount() : this.notFullTimeoutRetryCount;
|
||||
if (notFullTimeoutRetryCount != null && !notFullTimeoutRetryCount.equals(0)) {
|
||||
properties.setProperty(NOT_FULL_TIMEOUT_RETRY_COUNT, String.valueOf(notFullTimeoutRetryCount));
|
||||
}
|
||||
|
||||
Integer maxWaitThreadCount = this.maxWaitThreadCount == null ? g.getMaxWaitThreadCount() : this.maxWaitThreadCount;
|
||||
if (maxWaitThreadCount != null && !maxWaitThreadCount.equals(-1)) {
|
||||
properties.setProperty(MAX_WAIT_THREAD_COUNT, String.valueOf(maxWaitThreadCount));
|
||||
}
|
||||
|
||||
Boolean failFast = this.failFast == null ? g.getFailFast() : this.failFast;
|
||||
if (failFast != null && failFast.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(FAIL_FAST, "true");
|
||||
}
|
||||
|
||||
Long phyTimeoutMillis = this.phyTimeoutMillis == null ? g.getPhyTimeoutMillis() : this.phyTimeoutMillis;
|
||||
if (phyTimeoutMillis != null && !phyTimeoutMillis.equals(DEFAULT_PHY_TIMEOUT_MILLIS)) {
|
||||
properties.setProperty(PHY_TIMEOUT_MILLIS, String.valueOf(phyTimeoutMillis));
|
||||
}
|
||||
|
||||
Boolean keepAlive = this.keepAlive == null ? g.getKeepAlive() : this.keepAlive;
|
||||
if (keepAlive != null && keepAlive.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(KEEP_ALIVE, "true");
|
||||
}
|
||||
|
||||
Boolean poolPreparedStatements = this.poolPreparedStatements == null ? g.getPoolPreparedStatements() : this.poolPreparedStatements;
|
||||
if (poolPreparedStatements != null && poolPreparedStatements.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(POOL_PREPARED_STATEMENTS, "true");
|
||||
}
|
||||
|
||||
Boolean initVariants = this.initVariants == null ? g.getInitVariants() : this.initVariants;
|
||||
if (initVariants != null && initVariants.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(INIT_VARIANTS, "true");
|
||||
}
|
||||
|
||||
Boolean initGlobalVariants = this.initGlobalVariants == null ? g.getInitGlobalVariants() : this.initGlobalVariants;
|
||||
if (initGlobalVariants != null && initGlobalVariants.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(INIT_GLOBAL_VARIANTS, "true");
|
||||
}
|
||||
|
||||
Boolean useUnfairLock = this.useUnfairLock == null ? g.getUseUnfairLock() : this.useUnfairLock;
|
||||
if (useUnfairLock != null) {
|
||||
properties.setProperty(USE_UNFAIR_LOCK, String.valueOf(useUnfairLock));
|
||||
}
|
||||
|
||||
Boolean killWhenSocketReadTimeout =
|
||||
this.killWhenSocketReadTimeout == null ? g.getKillWhenSocketReadTimeout() : this.killWhenSocketReadTimeout;
|
||||
if (killWhenSocketReadTimeout != null && killWhenSocketReadTimeout.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(KILL_WHEN_SOCKET_READ_TIMEOUT, "true");
|
||||
}
|
||||
|
||||
Properties connectProperties = connectionProperties == null ? g.getConnectionProperties() : connectionProperties;
|
||||
|
||||
if (publicKey != null && publicKey.length() > 0) {
|
||||
if (connectProperties == null) {
|
||||
connectProperties = new Properties();
|
||||
}
|
||||
log.info("dynamic-datasource detect druid publicKey,It is highly recommended that you use the built-in encryption method");
|
||||
connectProperties.setProperty("config.decrypt", "true");
|
||||
connectProperties.setProperty("config.decrypt.key", publicKey);
|
||||
}
|
||||
this.connectionProperties = connectProperties;
|
||||
|
||||
Integer maxPoolPreparedStatementPerConnectionSize =
|
||||
this.maxPoolPreparedStatementPerConnectionSize == null ? g.getMaxPoolPreparedStatementPerConnectionSize()
|
||||
: this.maxPoolPreparedStatementPerConnectionSize;
|
||||
if (maxPoolPreparedStatementPerConnectionSize != null && !maxPoolPreparedStatementPerConnectionSize.equals(10)) {
|
||||
properties.setProperty(MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE, String.valueOf(maxPoolPreparedStatementPerConnectionSize));
|
||||
}
|
||||
|
||||
String initConnectionSqls = this.initConnectionSqls == null ? g.getInitConnectionSqls() : this.initConnectionSqls;
|
||||
if (initConnectionSqls != null && initConnectionSqls.length() > 0) {
|
||||
properties.setProperty(INIT_CONNECTION_SQLS, initConnectionSqls);
|
||||
}
|
||||
|
||||
//stat配置参数
|
||||
Integer statSqlMaxSize = this.statSqlMaxSize == null ? g.getStatSqlMaxSize() : this.statSqlMaxSize;
|
||||
if (statSqlMaxSize != null) {
|
||||
properties.setProperty(STAT_SQL_MAX_SIZE, String.valueOf(statSqlMaxSize));
|
||||
}
|
||||
|
||||
Boolean logSlowSql = stat.getLogSlowSql() == null ? g.stat.getLogSlowSql() : stat.getLogSlowSql();
|
||||
if (logSlowSql != null && logSlowSql) {
|
||||
properties.setProperty(STAT_LOG_SLOW_SQL, "true");
|
||||
}
|
||||
Long slowSqlMillis = stat.getSlowSqlMillis() == null ? g.stat.getSlowSqlMillis() : stat.getSlowSqlMillis();
|
||||
if (slowSqlMillis != null) {
|
||||
properties.setProperty(STAT_SLOW_SQL_MILLIS, slowSqlMillis.toString());
|
||||
}
|
||||
|
||||
Boolean mergeSql = stat.getMergeSql() == null ? g.stat.getMergeSql() : stat.getMergeSql();
|
||||
if (mergeSql != null && mergeSql) {
|
||||
properties.setProperty(STAT_MERGE_SQL, "true");
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
Integer maxActive = this.maxActive == null ? g.getMaxActive() : this.maxActive;
|
||||
if (maxActive != null && !maxActive.equals(DEFAULT_MAX_WAIT)) {
|
||||
properties.setProperty(MAX_ACTIVE, String.valueOf(maxActive));
|
||||
public List<String> getProxyFilters() {
|
||||
return proxyFilters;
|
||||
}
|
||||
|
||||
Integer minIdle = this.minIdle == null ? g.getMinIdle() : this.minIdle;
|
||||
if (minIdle != null && !minIdle.equals(DEFAULT_MIN_IDLE)) {
|
||||
properties.setProperty(MIN_IDLE, String.valueOf(minIdle));
|
||||
public void setProxyFilters(List<String> proxyFilters) {
|
||||
this.proxyFilters = proxyFilters;
|
||||
}
|
||||
|
||||
Integer maxWait = this.maxWait == null ? g.getMaxWait() : this.maxWait;
|
||||
if (maxWait != null && !maxWait.equals(DEFAULT_MAX_WAIT)) {
|
||||
properties.setProperty(MAX_WAIT, String.valueOf(maxWait));
|
||||
}
|
||||
|
||||
Long timeBetweenEvictionRunsMillis =
|
||||
this.timeBetweenEvictionRunsMillis == null ? g.getTimeBetweenEvictionRunsMillis() : this.timeBetweenEvictionRunsMillis;
|
||||
if (timeBetweenEvictionRunsMillis != null && !timeBetweenEvictionRunsMillis.equals(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS)) {
|
||||
properties.setProperty(TIME_BETWEEN_EVICTION_RUNS_MILLIS, String.valueOf(timeBetweenEvictionRunsMillis));
|
||||
}
|
||||
|
||||
Long timeBetweenLogStatsMillis =
|
||||
this.timeBetweenLogStatsMillis == null ? g.getTimeBetweenLogStatsMillis() : this.timeBetweenLogStatsMillis;
|
||||
if (timeBetweenLogStatsMillis != null && timeBetweenLogStatsMillis > 0) {
|
||||
properties.setProperty(TIME_BETWEEN_LOG_STATS_MILLIS, String.valueOf(timeBetweenLogStatsMillis));
|
||||
}
|
||||
|
||||
Long minEvictableIdleTimeMillis =
|
||||
this.minEvictableIdleTimeMillis == null ? g.getMinEvictableIdleTimeMillis() : this.minEvictableIdleTimeMillis;
|
||||
if (minEvictableIdleTimeMillis != null && !minEvictableIdleTimeMillis.equals(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS)) {
|
||||
properties.setProperty(MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(minEvictableIdleTimeMillis));
|
||||
}
|
||||
|
||||
Long maxEvictableIdleTimeMillis =
|
||||
this.maxEvictableIdleTimeMillis == null ? g.getMaxEvictableIdleTimeMillis() : this.maxEvictableIdleTimeMillis;
|
||||
if (maxEvictableIdleTimeMillis != null && !maxEvictableIdleTimeMillis.equals(DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS)) {
|
||||
properties.setProperty(MAX_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(maxEvictableIdleTimeMillis));
|
||||
}
|
||||
|
||||
Boolean testWhileIdle = this.testWhileIdle == null ? g.getTestWhileIdle() : this.testWhileIdle;
|
||||
if (testWhileIdle != null && !testWhileIdle.equals(DEFAULT_WHILE_IDLE)) {
|
||||
properties.setProperty(TEST_WHILE_IDLE, "false");
|
||||
}
|
||||
|
||||
Boolean testOnBorrow = this.testOnBorrow == null ? g.getTestOnBorrow() : this.testOnBorrow;
|
||||
if (testOnBorrow != null && !testOnBorrow.equals(DEFAULT_TEST_ON_BORROW)) {
|
||||
properties.setProperty(TEST_ON_BORROW, "true");
|
||||
}
|
||||
|
||||
String validationQuery = this.validationQuery == null ? g.getValidationQuery() : this.validationQuery;
|
||||
if (validationQuery != null && validationQuery.length() > 0) {
|
||||
properties.setProperty(VALIDATION_QUERY, validationQuery);
|
||||
}
|
||||
|
||||
Boolean useGlobalDataSourceStat = this.useGlobalDataSourceStat == null ? g.getUseGlobalDataSourceStat() : this.useGlobalDataSourceStat;
|
||||
if (useGlobalDataSourceStat != null && useGlobalDataSourceStat.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(USE_GLOBAL_DATA_SOURCE_STAT, "true");
|
||||
}
|
||||
|
||||
Boolean asyncInit = this.asyncInit == null ? g.getAsyncInit() : this.asyncInit;
|
||||
if (asyncInit != null && asyncInit.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(ASYNC_INIT, "true");
|
||||
}
|
||||
|
||||
//filters单独处理,默认了stat,wall
|
||||
String filters = this.filters == null ? g.getFilters() : this.filters;
|
||||
if (filters == null) {
|
||||
filters = "stat,wall";
|
||||
}
|
||||
if (publicKey != null && publicKey.length() > 0 && !filters.contains("config")) {
|
||||
filters += ",config";
|
||||
}
|
||||
properties.setProperty(FILTERS, filters);
|
||||
|
||||
Boolean clearFiltersEnable = this.clearFiltersEnable == null ? g.getClearFiltersEnable() : this.clearFiltersEnable;
|
||||
if (clearFiltersEnable != null && clearFiltersEnable.equals(Boolean.FALSE)) {
|
||||
properties.setProperty(CLEAR_FILTERS_ENABLE, "false");
|
||||
}
|
||||
|
||||
Boolean resetStatEnable = this.resetStatEnable == null ? g.getResetStatEnable() : this.resetStatEnable;
|
||||
if (resetStatEnable != null && resetStatEnable.equals(Boolean.FALSE)) {
|
||||
properties.setProperty(RESET_STAT_ENABLE, "false");
|
||||
}
|
||||
|
||||
Integer notFullTimeoutRetryCount =
|
||||
this.notFullTimeoutRetryCount == null ? g.getNotFullTimeoutRetryCount() : this.notFullTimeoutRetryCount;
|
||||
if (notFullTimeoutRetryCount != null && !notFullTimeoutRetryCount.equals(0)) {
|
||||
properties.setProperty(NOT_FULL_TIMEOUT_RETRY_COUNT, String.valueOf(notFullTimeoutRetryCount));
|
||||
}
|
||||
|
||||
Integer maxWaitThreadCount = this.maxWaitThreadCount == null ? g.getMaxWaitThreadCount() : this.maxWaitThreadCount;
|
||||
if (maxWaitThreadCount != null && !maxWaitThreadCount.equals(-1)) {
|
||||
properties.setProperty(MAX_WAIT_THREAD_COUNT, String.valueOf(maxWaitThreadCount));
|
||||
}
|
||||
|
||||
Boolean failFast = this.failFast == null ? g.getFailFast() : this.failFast;
|
||||
if (failFast != null && failFast.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(FAIL_FAST, "true");
|
||||
}
|
||||
|
||||
Long phyTimeoutMillis = this.phyTimeoutMillis == null ? g.getPhyTimeoutMillis() : this.phyTimeoutMillis;
|
||||
if (phyTimeoutMillis != null && !phyTimeoutMillis.equals(DEFAULT_PHY_TIMEOUT_MILLIS)) {
|
||||
properties.setProperty(PHY_TIMEOUT_MILLIS, String.valueOf(phyTimeoutMillis));
|
||||
}
|
||||
|
||||
Boolean keepAlive = this.keepAlive == null ? g.getKeepAlive() : this.keepAlive;
|
||||
if (keepAlive != null && keepAlive.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(KEEP_ALIVE, "true");
|
||||
}
|
||||
|
||||
Boolean poolPreparedStatements = this.poolPreparedStatements == null ? g.getPoolPreparedStatements() : this.poolPreparedStatements;
|
||||
if (poolPreparedStatements != null && poolPreparedStatements.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(POOL_PREPARED_STATEMENTS, "true");
|
||||
}
|
||||
|
||||
Boolean initVariants = this.initVariants == null ? g.getInitVariants() : this.initVariants;
|
||||
if (initVariants != null && initVariants.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(INIT_VARIANTS, "true");
|
||||
}
|
||||
|
||||
Boolean initGlobalVariants = this.initGlobalVariants == null ? g.getInitGlobalVariants() : this.initGlobalVariants;
|
||||
if (initGlobalVariants != null && initGlobalVariants.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(INIT_GLOBAL_VARIANTS, "true");
|
||||
}
|
||||
|
||||
Boolean useUnfairLock = this.useUnfairLock == null ? g.getUseUnfairLock() : this.useUnfairLock;
|
||||
if (useUnfairLock != null) {
|
||||
properties.setProperty(USE_UNFAIR_LOCK, String.valueOf(useUnfairLock));
|
||||
}
|
||||
|
||||
Boolean killWhenSocketReadTimeout =
|
||||
this.killWhenSocketReadTimeout == null ? g.getKillWhenSocketReadTimeout() : this.killWhenSocketReadTimeout;
|
||||
if (killWhenSocketReadTimeout != null && killWhenSocketReadTimeout.equals(Boolean.TRUE)) {
|
||||
properties.setProperty(KILL_WHEN_SOCKET_READ_TIMEOUT, "true");
|
||||
}
|
||||
|
||||
Properties connectProperties = connectionProperties == null ? g.getConnectionProperties() : connectionProperties;
|
||||
|
||||
if (publicKey != null && publicKey.length() > 0) {
|
||||
if (connectProperties == null) {
|
||||
connectProperties = new Properties();
|
||||
}
|
||||
log.info("dynamic-datasource detect druid publicKey,It is highly recommended that you use the built-in encryption method");
|
||||
connectProperties.setProperty("config.decrypt", "true");
|
||||
connectProperties.setProperty("config.decrypt.key", publicKey);
|
||||
}
|
||||
this.connectionProperties = connectProperties;
|
||||
|
||||
Integer maxPoolPreparedStatementPerConnectionSize =
|
||||
this.maxPoolPreparedStatementPerConnectionSize == null ? g.getMaxPoolPreparedStatementPerConnectionSize()
|
||||
: this.maxPoolPreparedStatementPerConnectionSize;
|
||||
if (maxPoolPreparedStatementPerConnectionSize != null && !maxPoolPreparedStatementPerConnectionSize.equals(10)) {
|
||||
properties.setProperty(MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE, String.valueOf(maxPoolPreparedStatementPerConnectionSize));
|
||||
}
|
||||
|
||||
String initConnectionSqls = this.initConnectionSqls == null ? g.getInitConnectionSqls() : this.initConnectionSqls;
|
||||
if (initConnectionSqls != null && initConnectionSqls.length() > 0) {
|
||||
properties.setProperty(INIT_CONNECTION_SQLS, initConnectionSqls);
|
||||
}
|
||||
|
||||
//stat配置参数
|
||||
Integer statSqlMaxSize = this.statSqlMaxSize == null ? g.getStatSqlMaxSize() : this.statSqlMaxSize;
|
||||
if (statSqlMaxSize != null) {
|
||||
properties.setProperty(STAT_SQL_MAX_SIZE, String.valueOf(statSqlMaxSize));
|
||||
}
|
||||
|
||||
Boolean logSlowSql = stat.getLogSlowSql() == null ? g.stat.getLogSlowSql() : stat.getLogSlowSql();
|
||||
if (logSlowSql != null && logSlowSql) {
|
||||
properties.setProperty(STAT_LOG_SLOW_SQL, "true");
|
||||
}
|
||||
Long slowSqlMillis = stat.getSlowSqlMillis() == null ? g.stat.getSlowSqlMillis() : stat.getSlowSqlMillis();
|
||||
if (slowSqlMillis != null) {
|
||||
properties.setProperty(STAT_SLOW_SQL_MILLIS, slowSqlMillis.toString());
|
||||
}
|
||||
|
||||
Boolean mergeSql = stat.getMergeSql() == null ? g.stat.getMergeSql() : stat.getMergeSql();
|
||||
if (mergeSql != null && mergeSql) {
|
||||
properties.setProperty(STAT_MERGE_SQL, "true");
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
public List<String> getProxyFilters() {
|
||||
return proxyFilters;
|
||||
}
|
||||
|
||||
public void setProxyFilters(List<String> proxyFilters) {
|
||||
this.proxyFilters = proxyFilters;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user