SpringBoot整合JDBCTemplate以及多数据源

Lou.Chen
大约 4 分钟

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

当有多个配置文件时

标记为默认的注入配置