本文是读《Spring Boot2精髓-从构件小系统到架构分布式大系统》的读书笔记。
本章介绍 Spring JDBC Template 和 BeetlSQL 两种数据库访问方式, JDBC Template 是 Spring自带的,在 JDBC 的基础上做了 一定封装,而 BeetlSQL 是作者开发的这里不做介绍。都是以 SQL 为核心 。
以SQL 为中心或者以对象为中心,两种访问方式没有绝对的好坏, 一般来说,以 SQL 为
核心的数据库访问更为灵活,更能适应大型的互联网和企业应用,学习门槛较低 。 以对象方式访问数据库更适合较为简单的系统或者工具类系统,学习门槛刚开始较低,但因为 ORM(ObjectRelational Mapping)持久化上下文等概念过于复杂,导致后期深入学习较为困难 。
5.1 配置数据源
本章将使用号称最快的数据库连接池 HikariCP 来说明 JDBC Template 和 BeetlSQL,集成
HikariCP 到 Spring Boot,首先在 porn 中加入如下依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
本例使用了问ySQL ,你也可以使用任何其他驱动来完成本章的例子 , 使用 MySQL需要在 porn 中配置 MySQL 驱 动 依赖 。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
配置好上述依赖包和配置文件后,需要写一个 Java Config 来创建一个数据源,代码如下:
package com.bee.sample.ch5.conf;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource")
public DataSource datasource(Environment env) {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(env.getProperty("spring.datasource.url"));
ds.setUsername(env.getProperty("spring.datasource.username"));
ds.setPassword(env.getProperty("spring.datasource.password"));
ds.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
return ds;
}
}
以上代码创建了 一个叫 dataSource 的数据源,我们使用 HikariDataSource 。
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_bin DEFAULT NULL COMMENT '名称',
`department_id` int(11) DEFAULT NULL,
`create_time` date DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `user` VALUES (1, 'helo', 1, '2017-4-21 11:52:41');
INSERT INTO `department` VALUES ('1', '研发部门');
5.2 Spring JDBC Template
Spring 提供了 JdbcTemplate 对数据库访问技术 JDBC 做了 一定封装 ,包括管理数据库连接,简单查询结果映射成 Java 对象,复杂的结果集通过实现 RowMapper 接口来映射到 Java 对象 。
在 Spring Boot 中 ,只要配置好数据源 DataSource , 就能自动使用 JdbcTemplate .
查询:
一个简单的返回总数的查询:
int rowCount = this.jdbcTemplate.queryForObject (” select count (*) from user” ,Integer.class) ;
一个带参数绑定的查询:
String rowCount = this . jdbcTemplate.queryForOb] ect (” select count(*) from user where department id=? ”, Integer . class ,l);
如果期望返回 POJO 实例, JdbcTemplate 需要一个 RowMapper , 将查询结果集 ResultSet 映射成一个对象:
通常 RowMapp巳r 可以被其他查询复用,因此最好的办法是在 DAO 中创建一个内部类,然后在 user 的查询中使用此类:
public class UserDao{
static class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setDepartmentId(rs.getInt("department_id"));
return user;
}
}
}
JdbcTemplate 查询如果期望返回的是列表 ,则 需要使用 query 方法 :
public List<User> getUserByDepartmentId(Long departmenetId) {
String sql = "select * from user where department_id=? ";
List<User> user = jdbcTempalte.query(sql, new UserRowMapper(), 1);
return user;
}
修改:
JdbcTempalte 提供 update 方法来实现 SQL 的修改语旬,包括新增、修改、删除、执行存储过程等。
String sql =”update user set name=? and departmet_id=? where id = ?” ;
jdbcTempalte.update(sql,user.getName(),user.getDepartmentid(),user.getid()) ;
如果是数据库插入,操作同上面的 update,对于 MySQL、 SQL Server等数据库,含有自增序列 , 则需要提供一个 KeyHolder 来放置返回的序列 :
public Integer insertUser(final User user) {
final String sql = "insert into user (name, departmet_id ) values (?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTempalte.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
//指出自增主键的列名
PreparedStatement ps = connection.prepareStatement(sql, new String[] { "id" });
ps.setString(1, user.getName());
ps.setInt(2, user.getDepartmentId());
return ps;
}
}, keyHolder);
return keyHolder.getKey().intValue();
}
JdbcTemplate:
N amedParameterJdbcTemplate 继承了 JdbcTemplate , 不同于 JdbcTemplate , 对 SQL 中的参数只支持传统的“?”占位符。NamedParameterJdbcTemplate 允许 SQL 中使用参数的名字作为占位符。
Spring Boot 己经自动配置了 NamedParameterJdbcTemplate,可以自动注入使用 :
@Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate ;
public Integer totalUserInDepartment2(Long departmentId) {
String sql = "select count(1) from user where department_id=:deptId";
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("deptId", departmentId);
Integer count = namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class) ;
return count;
}
MapSqlParameterSource 是一个类似 Map 风格的类,包含 Key-Value, Key 就是 SQL 中的参数名字,在 SQL 语句中,不再使用“?”,而是使用了“:”开头的参数名字 ,如“:deptld ”。
BeetlSQL介绍
这里不作说明
针对 Spring JDBC Template存在 的一些问题,可以引申学习一下Mybatis
框架。
JPA具有内置多种DAO操作功能的优点
MyBatis具有SQL集中管理的优点
JdbcTemplate 和 mybatis 的对比
谈jdbcTemplate与mybatis
这两篇博文可以看一下