SpringBoot数据持久化之JdbcTemplate
1.单数据源
在Java领域,数据持久化有几个常见的方案,有Spring自带的JdbcTemplate、有MyBatis,还有JPA,在这些方案中,最简单的就是Spring自带的JdbcTemplate了,这个东西虽然没有MyBatis那么方便,但是比起最开始的Jdbc已经强了很多了,它没有MyBatis功能那么强大,当然也意味着它的使用比较简单,事实上,JdbcTemplate算是最简单的数据持久化方案了
我们可以创建springboot项目,引入下面jar
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<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>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
<scope>runtime</scope>
</dependency>
项目创建完后,接下来只需要在application.properties中提供数据的基本配置即可,如下:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=UTF-8
首先我们来创建一个User Bean,如下:
public class User {
private Long id;
private String username;
private String address;
//省略getter/setter
}
然后来创建一个UserService类,在UserService类中注入JdbcTemplate,如下:
@Service
public class UserService {
@Autowired
JdbcTemplate jdbcTemplate;
}
到此我们准备工作完成
JdbcTemplate中,除了查询有几个API之外,增删改统一都使用update来操作,自己来传入SQL即可。例如添加数据,方法如下:
public int addUser(User user) {
return jdbcTemplate.update("insert into user (username,address) values (?,?);", user.getUsername(), user.getAddress());
}
update方法的返回值就是SQL执行受影响的行数。
这里只需要传入SQL即可,如果你的需求比较复杂,例如在数据插入的过程中希望实现主键回填,那么可以使用PreparedStatementCreator,如下:
public int addUser2(User user) {
KeyHolder keyHolder = new GeneratedKeyHolder();
int update = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement("insert into user (username,address) values (?,?);", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, user.getUsername());
ps.setString(2, user.getAddress());
return ps;
}
}, keyHolder);
user.setId(keyHolder.getKey().longValue());
System.out.println(user);
return update;
}
实际上这里就相当于完全使用了JDBC中的解决方案了,首先在构建PreparedStatement时传入Statement.RETURN_GENERATED_KEYS,然后传入KeyHolder,最终从KeyHolder中获取刚刚插入数据的id保存到user对象的id属性中去。
查询的话,稍微有点变化,这里主要向大伙介绍query方法,例如查询所有用户:
public List<User> getAllUsers() {
return jdbcTemplate.query("select * from user", new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
String username = resultSet.getString("username");
String address = resultSet.getString("address");
long id = resultSet.getLong("id");
User user = new User();
user.setAddress(address);
user.setUsername(username);
user.setId(id);
return user;
}
});
}
查询的时候需要提供一个RowMapper,就是需要自己手动映射,将数据库中的字段和对象的属性一一对应起来,实际上,如果数据库中的字段和对象属性的名字一模一样的话,有另外一个简单的方案,如下:
public List<User> getAllUsers2() {
return jdbcTemplate.query("select * from user", new BeanPropertyRowMapper<>(User.class));
}
除了这些基本用法之外,JdbcTemplate也支持其他用法,例如调用存储过程等,这些都比较容易,而且和Jdbc本身都比较相似,这里也就不做介绍了,有兴趣可以留言讨论。
2.多数据源
多数据源配置也算是一个常见的开发需求,Spring和SpringBoot中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,还是建议首选分布式数据库中间件MyCat去解决相关问题,分表策略使用sharding-by-intfile,当然如果一些简单的需求,还是可以使用多数据源的,Spring Boot中,JdbcTemplate、MyBatis以及Jpa都可以配置多数据源
首先我们创建springboot项目,创建成功之后,一定接下来手动添加Druid依赖,由于这里一会需要开发者自己配置DataSoruce,所以这里必须要使用druid-spring-boot-starter依赖,而不是传统的那个druid依赖,因为druid-spring-boot-starter依赖提供了DruidDataSourceBuilder类,这个可以用来构建一个DataSource实例,而传统的Druid则没有该类。完整的依赖如下
<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>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
接下来,在application.properties中配置数据源,这里的数据源需要配置两个,如下:
spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=root
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=root
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
这里通过one和two对数据源进行了区分,但是加了one和two之后,这里的配置就没法被SpringBoot自动加载了(因为前面的key变了),需要我们自己去加载DataSource了,此时,需要自己配置一个DataSourceConfig,用来提供两个DataSource Bean,如下:
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}
这里提供了两个Bean,其中@ConfigurationProperties是Spring Boot提供的类型安全的属性绑定,以第一个Bean为例,@ConfigurationProperties(prefix = “spring.datasource.one”)表示使用spring.datasource.one前缀的数据库配置去创建一个DataSource,这样配置之后,我们就有了两个不同的DataSource,接下来再用这两个不同的DataSource去创建两个不同的JdbcTemplate。
创建JdbcTemplateConfig类,用来提供两个不同的JdbcTemplate实例,如下:
@Configuration
public class JdbcTemplateConfig {
@Bean
JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {
return new JdbcTemplate(dsOne);
}
@Bean
JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo") DataSource dsTwo) {
return new JdbcTemplate(dsTwo);
}
}
每一个JdbcTemplate的创建都需要一个DataSource,由于Spring容器中现在存在两个DataSource,默认使用类型查找,会报错,因此加上@Qualifier注解,表示按照名称查找。这里创建了两个JdbcTemplate实例,分别对应了两个DataSource。
接下来直接去使用这个JdbcTemplate就可以了。
在Controller中注入两个不同的JdbcTemplate,这两个JdbcTemplate分别对应了不同的数据源,如下:
@RestController
public class HelloController {
@Autowired
@Qualifier("jdbcTemplateOne")
JdbcTemplate jdbcTemplateOne;
@Resource(name = "jdbcTemplateTwo")
JdbcTemplate jdbcTemplateTwo;
@GetMapping("/user")
public List<User> getAllUser() {
List<User> list = jdbcTemplateOne.query("select * from t_user", new BeanPropertyRowMapper<>(User.class));
return list;
}
@GetMapping("/user2")
public List<User> getAllUser2() {
List<User> list = jdbcTemplateTwo.query("select * from t_user", new BeanPropertyRowMapper<>(User.class));
return list;
}
}
和DataSource一样,Spring容器中的JdbcTemplate也是有两个,因此不能通过byType的方式注入进来,这里给大伙提供了两种注入思路,一种是使用@Resource注解,直接通过byName的方式注入进来,另外一种就是@Autowired注解加上@Qualifier注解,两者联合起来,实际上也是byName。将JdbcTemplate注入进来之后,jdbcTemplateOne和jdbcTemplateTwo此时就代表操作不同的数据源,使用不同的JdbcTemplate操作不同的数据源,实现了多数据源配置。
到此介绍完成,望评论关注!