2018-12-21 · Develop

数据库访问 - Spring JDBC Template

通过 Spring Boot 对关系型数据库的访问主要集中在 Spring JDBC Template、Spring Data JPA 和 Mybatis 三种方式上。
JDBC Template 是 Spring 自带的,在 JDBC 的基础上做了一定封装,包括管理数据库连接,简单查询结果到 Java Bean 之间的映射,复杂的结果集需要通过 RowMapper 接口来映射。由于是 Spring 自带的,所以使用上及其方便,只需要配置好数据源就可以直接使用。

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.113.131:3306/lo?useUnicode=true&characterEncoding=UTF-8 &autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
    username: lo
    password: lo
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 15
      auto-commit: true
      idle-timeout: 30000
      pool-name: LoHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1

当然数据库的驱动包是少不了的,然后就是创建库表来进行测试。

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;

根据表创建相应的实体类

@Getter
@Setter
@Builder
@ToString
public class User {
    private Long id;
    private String name;
    private Long departmentId;
    private Date createTime;
}
@Getter
@Setter
@Builder
@ToString
public class Department {
    private Long id;
    private String name;
}

有了上面的准备工作,下面我们就开始进行 Dao 层的编写,由于结果集到 JavaBean 之间的转换需要使用 RowMapper 接口进行,并且使用的地方很多,所以将其抽离出来:

public interface UserDao {
    // 返回主键 ID 的值
    Long insert(User user);

    User selectById(Long id);

    int updateNameById(Long id, String name);

    int deleteById(Long id);

    class UserRowMapper implements RowMapper<User> {
        @Nullable
        @Override
        public User mapRow(ResultSet resultSet, int i) throws SQLException {
            return User.builder()
                    .id(resultSet.getLong("id"))
                    .name(resultSet.getString("name"))
                    .departmentId(resultSet.getLong("department_id"))
                    .build();
        }
    }
}
@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Override
    public Long insert(User user) {
        String sql = "insert into `user` (`name`, `department_id`) values (?, ?)";
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(connection -> {
            PreparedStatement preparedStatement = connection.prepareStatement(sql, new String[]{"id"});
            preparedStatement.setString(1, user.getName());
            preparedStatement.setLong(2, user.getDepartmentId());
            return preparedStatement;
        }, keyHolder);
        return keyHolder.getKey().longValue();
    }

    @Override
    public User selectById(Long id) {
        String sql = "select * from `user` where `id` = ?";
        return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
    }

    public int updateNameById(Long id, String name) {
        String sql = "update `user` set `name` = :name where `id` = :id";
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        mapSqlParameterSource.addValue("id", id);
        mapSqlParameterSource.addValue("name", name);
        return namedParameterJdbcTemplate.update(sql, mapSqlParameterSource);
    }

    public int deleteById(Long id) {
        String sql = "delete from `user` where `id` = :id";
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        mapSqlParameterSource.addValue("id", id);
        return namedParameterJdbcTemplate.update(sql, mapSqlParameterSource);
    }
}

其中的 KeyHolder 可以用来放置自增序列返回的序列值。但是并不能确定其序列的类型,需要更具需求转换为想要的类型。
NamedParameterJdbcTemplate 继承至 JdbcTemplate 对其进行了增强,对 SQL 中的参数从“?” 占位符到支持参数名称作为占位符的增强。不再使用 “?” 而是使用 “:” 加参数名字,比如 “:id”。