SpringBoot整合JDBCTemplate以及多数据源
springboot整合JDBCTemplate
源码分析
==>
当我们没有配置任何jdbcTemplate时,springboot自动为我们创建了一个jdbctemplate
当我们配置了jdbctemplate时候,自动配置失效
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration
==>
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({JdbcOperations.class})
class JdbcTemplateConfiguration {
JdbcTemplateConfiguration() {
}
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
private boolean ignoreWarnings = true;
private int fetchSize = -1;
private int maxRows = -1;
private int queryTimeout = -1;
private boolean skipResultsProcessing = false;
private boolean skipUndeclaredResults = false;
private boolean resultsMapCaseInsensitive = false;
//****
//****
}
单数据源配置:
pom.xml
<dependencies>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<!--只会在测试时使用 不会被打包-->
<scope>test</scope>
</dependency>
<!--jdbctemplate操作-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--阿里的starter-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.18</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--只会在项目运行和测试时有效 不会随着项目一起打包发布-->
<scope>runtime</scope>
<version>5.1.27</version>
</dependency>
</dependencies>
spring:
# 数据源配置
datasource:
#数据源类型
type: com.alibaba.druid.pool.DruidDataSource
# 驱动类
driver-class-name: com.mysql.jdbc.Driver
# 数据库地址
url: jdbc:mysql://127.0.0.1:3306/test
# 用户名
username: root
# 密码
password: 123456
public class User {
private Integer id;
private String username;
private String address;
//settter
//getter
//toStr·ing
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 添加操作
* @param user
* @return
*/
public Integer addUser(User user){
return jdbcTemplate.update("insert into user(username,address) values(?,?)", user.getUsername(), user.getAddress());
}
/**
* 删除操作
* @param integer
* @return
*/
public Integer deleteUser(Integer integer) {
return jdbcTemplate.update("delete from user where id =?", integer);
}
/**
* 更新操作
* @param user
* @return
*/
public Integer updateUser(User user) {
return jdbcTemplate.update("update user set address=? where id=?", user.getAddress(), user.getId());
}
/**
* 获取所有 并传递参数
* 一般属性名和数据库字段名不一致时手动设置值
* @return
*/
public List<User> getAllUser(User user){
return jdbcTemplate.query("select * from user where address =?",new Object[]{user.getAddress()}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user=new User();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setAddress(resultSet.getString("address"));
return user;
}
});
}
/**
* 属性名和数据库字段名一致的情况
* @param user
* @return
*/
public List<User> getAllUserSameArgs(User user){
return jdbcTemplate.query("select * from user where address =?", new Object[]{user.getAddress()}, new BeanPropertyRowMapper<>(User.class));
}
}
测试使用:
@SpringBootTest(classes = JDBCTemplateApplication.class)
@RunWith(SpringRunner.class)
public class JDBCTemplateTest {
@Autowired
private UserService userService;
@Test
public void test01() {
User user=new User();
user.setUsername("张三").setAddress("湖北孝感");
Integer integer = userService.addUser(user);
System.out.println(integer);
}
@Test
public void test02() {
Integer integer = userService.deleteUser(1);
System.out.println(integer);
}
@Test
public void test03() {
Integer integer = userService.updateUser(new User().setId(1).setAddress("上海"));
System.out.println(integer);
}
@Test
public void test04() {
List<User> allUser = userService.getAllUserSameArgs(new User().setAddress("武汉"));
System.out.println(allUser);
}
}
多数据源配置:
pom.xml和单数据源一致
这里注意,在yaml文件中,属性名的字母不要写大写,大写字母前加 - 后转小写
#配置多数据后,所有的数据源自动配置将会失效
spring:
#数据源1
datasourceone:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
#传输时 使用统一的utf-8编码
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
#数据源2
datasourcetwo:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
#传输时 使用统一的utf-8编码
url: jdbc:mysql://47.96.141.44:3306/test?useUnicode=true&characterEncoding=UTF-8
username: root
password: xxxxxxx
数据源配置注入
==>
@Configuration
public class DataSourceConfig {
@Bean
//配置前缀和yaml中的属性对应,完成属性的安全注入
@ConfigurationProperties(prefix = "spring.datasourceone")
public DataSource dataSourceOne(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasourcetwo")
public DataSource dataSourceTwo(){
return DruidDataSourceBuilder.create().build();
}
}
jdbcTemplate配置
==>
@Autowired 默认按照类型进行注入``(多个或者找不到报错)
@Qualifier
按照名称进行配置
一般是结合起来使用==>
如:
@Qualifier("dataSourceOne") @Autowired private DataSource dataSourceOne
@Resource 默认直接按照名称进行注入
(可同时指定name和type一起查找注入,也可都省略)注意@Resource不能存在于方法的参数上
如:
@Resource(name = "dataSourceTwo")
DataSource dataSourceTwo;
@Configuration
public class JDBCTemplateConfig {
@Bean
public JdbcTemplate jdbcTemplateOne(@Qualifier("dataSourceOne")DataSource dataSource){
return new JdbcTemplate(dataSource);
}
@Resource(name = "dataSourceTwo")DataSource dataSource;
@Bean
public JdbcTemplate jdbcTemplateTwo(){
return new JdbcTemplate(dataSource);
}
}
这里数据库的结构和实体两个数据源中的保持一致
先从数据源一查询一个用户,再把该用户插入另一个数据源
==>
@Service
public class UserToUserService {
@Qualifier("jdbcTemplateOne")
@Autowired
private JdbcTemplate jdbcTemplateOne;
@Qualifier("jdbcTemplateTwo")
@Autowired
private JdbcTemplate jdbcTemplateTwo;
public Integer userToAddUser(User user) {
List<User> list= jdbcTemplateOne.query("select * from user where id =?", new Object[]{user.getId()}, new BeanPropertyRowMapper<>(User.class));
if(list!=null&&!list.isEmpty()&&list.size()==1){
User resUser = list.get(0);
int update = jdbcTemplateTwo.update("insert into user(id,username,address) values (?,?,?)", resUser.getId(), resUser.getUsername(), resUser.getAddress());
if(update==1){
return 1;
}
}
return 0;
}
}
注意:当我们有多个数据源和多个jdbcTemplate配置的时候,我们在注入jdbctemplate的时候必须加限定名,即哪个jdbctemplate。
@Service
public class UserService {
@Qualifier("jdbcTemplateTwo")
@Autowired
private JdbcTemplate jdbcTemplate;
}
否则需要在数据源和jdbctemplate配置上加默认配置
即注解**@Primary**
@Configuration
public class DataSourceConfig {
@Primary
@Bean
@ConfigurationProperties(prefix = "spring.datasourceone")
public DataSource dataSourceOne(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasourcetwo")
public DataSource dataSourceTwo(){
return DruidDataSourceBuilder.create().build();
}
}
@Configuration
public class JDBCTemplateConfig {
@Primary
@Bean
public JdbcTemplate jdbcTemplateOne(@Qualifier("dataSourceOne")DataSource dataSource){
return new JdbcTemplate(dataSource);
}
@Resource(name = "dataSourceTwo")DataSource dataSource;
@Bean
public JdbcTemplate jdbcTemplateTwo(){
return new JdbcTemplate(dataSource);
}
}
我们在使用时,直接注入即可(默认注入标记的默认数据源)
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
}
注解
@Autowired
默认按照类型进行注入(多个或者找不到报错)
@Qualifier
按照名称进行配置
一般是结合起来使用==>
如:
@Qualifier("dataSourceOne") @Autowired private DataSource dataSourceOne
@Resource 默认直接按照名称进行注入
(可同时指定name和type一起查找注入,也可都省略)注意@Resource不能存在于方法的参数上
如:
@Resource(name = "dataSourceTwo")
DataSource dataSourceTwo;
@Primary
当有多个配置文件时
标记为默认的注入配置