SpringBoot高级篇JdbcTemplate之数据更新与删除

简介: 前面介绍了JdbcTemplate的插入数据和查询数据,占用CURD中的两项,本文则将主要介绍数据更新和删除。从基本使用上来看,姿势和前面的没啥两样

前面介绍了JdbcTemplate的插入数据和查询数据,占用CURD中的两项,本文则将主要介绍数据更新和删除。从基本使用上来看,姿势和前面的没啥两样


I. 环境准备



环境依然借助前面一篇的配置,链接如: 190407-SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解


或者直接查看项目源码: github.com/liuyueyi/sp…


我们查询所用数据,正是前面一篇插入的结果,如下图


image.png


II. 更新使用说明



对于数据更新,这里会分为两种进行说明,单个和批量;这个单个并不是指只能一条记录,主要针对的是sql的数量而言


1. update 方式


看过第一篇数据插入的童鞋,应该也能发现,新增数据也是用的这个方法,下面会介绍三种不同的使用姿势


先提供一个数据查询的转换方法,用于对比数据更新前后的结果


private MoneyPO queryById(int id) {
    return jdbcTemplate.queryForObject(
            "select id, `name`, money, is_deleted as isDeleted, unix_timestamp(create_at) as " +
                    "created, unix_timestamp(update_at) as updated from money where id=?",
            new BeanPropertyRowMapper<>(MoneyPO.class), id);
}
复制代码


a. 纯sql更新


这个属于最基本的方式了,前面几篇博文中大量使用了,传入一条完整的sql,执行即可


int id = 10;
// 最基本的sql更新
String sql = "update money set money=money + 999 where id =" + id;
int ans = jdbcTemplate.update(sql);
System.out.println("basic update: " + ans + " | db: " + queryById(id));
复制代码


b. 占位sql


问好占位,实际内容通过参数传递方式

// 占位方式
sql = "update money set money=money + ? where id = ?";
ans = jdbcTemplate.update(sql, 888, id);
System.out.println("placeholder update: " + ans + " | db: " + queryById(id));
复制代码


c. statement


从前面的几篇文章中可以看出,使用statement的方式,最大的好处有几点


  • 可以点对点的设置填充参数
  • PreparedStatementCreator 方式可以获取db连接,主动设置各种参数


下面给出两个常见的使用方式

// 通过 PreparedStatementCreator 方式更新
ans = jdbcTemplate.update(new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
        // 设置自动提交,设置100ms的超时,这种方式最大的好处是可以控制db连接的参数
        try {
            connection.setAutoCommit(true);
            connection.setNetworkTimeout(Executors.newSingleThreadExecutor(), 10);
            PreparedStatement statement =
                    connection.prepareStatement("update money set money=money + ? where id " + "= ?");
            statement.setInt(1, 777);
            statement.setInt(2, id);
            return statement;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
});
System.out.println("statementCreator update: " + ans + " | db: " + queryById(id));
// 通过 PreparedStatementSetter 来设置占位参数值
ans = jdbcTemplate.update(sql, new PreparedStatementSetter() {
    @Override
    public void setValues(PreparedStatement preparedStatement) throws SQLException {
        preparedStatement.setInt(1, 666);
        preparedStatement.setInt(2, id);
    }
});
System.out.println("statementSetter update: " + ans + " | db: " + queryById(id));
复制代码


注意下第一种调用中,设置了超时时间,下面给出一个动图,演示超时的使用姿势

image.png


在上图中,

  • 首先是一个开启一个事物,并修改了一条记录,这个时候这条记录会加上写锁
  • 然后JdbcTemplate中修改上面的这条记录,尝试加写锁,但是会失败,所以一直阻塞,当超时之后,抛出异常


2. batchUpdate 方式


批量方式,执行多个sql,从使用上看和前面没有太大的区别,先给出一个查询的通用方法


private List<MoneyPO> queryByIds(List<Integer> ids) {
    StringBuilder strIds = new StringBuilder();
    for (Integer id : ids) {
        strIds.append(id).append(",");
    }
    return jdbcTemplate.query("select id, `name`, money, is_deleted as isDeleted, unix_timestamp(create_at) as " +
            "created, unix_timestamp(update_at) as updated from money where id in (" +
            strIds.substring(0, strIds.length() - 1) + ")", new BeanPropertyRowMapper<>(MoneyPO.class));
}
复制代码


a. 纯sql更新


// 批量修改,
// 执行多条sql的场景
int[] ans = jdbcTemplate
        .batchUpdate("update money set money=1300 where id =10", "update money set money=1300 where id = 11");
System.out.println(
        "batch update by sql ans: " + Arrays.asList(ans) + " | db: " + queryByIds(Arrays.asList(10, 11)));
复制代码


b. 占位sql


// 占位替换方式
ans = jdbcTemplate.batchUpdate("update money set money=money + ? where id = ?",
        Arrays.asList(new Object[]{99, 10}, new Object[]{99, 11}));
System.out.println("batch update by placeHolder ans: " + Arrays.asList(ans) + " | db: " +
        queryByIds(Arrays.asList(10, 11)));
复制代码


c. statement


// 通过 statement
ans = jdbcTemplate
        .batchUpdate("update money set money=money + ? where id = ?", new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
                preparedStatement.setInt(1, 99);
                preparedStatement.setInt(2, i + 10);
            }
            @Override
            public int getBatchSize() {
                return 2;
            }
        });
System.out.println(
        "batch update by statement ans: " + Arrays.asList(ans) + " | db: " + queryByIds(Arrays.asList(10, 11)));
复制代码


注意下上面的方法中,getBatchSize返回实际的sql条数,setValues中的i从0开始


3. 测试


原始数据中,money都是300,通过一系列的修改,输出如下

image.png


III. 数据删除



删除的操作姿势和上面基本一样,也就是sql的写法不同罢了,因此没有太大的必要重新写一篇,下面给出一个简单的demo


@Component
public class DeleteService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public void delete() {
        int ans = jdbcTemplate.update("delete from money where id = 13");
        System.out.println("delete: " + ans);
    }
}



相关文章
|
4月前
|
消息中间件 缓存 监控
spring boot 高级篇
spring boot 高级篇
104 1
|
4月前
|
Java 数据安全/隐私保护
SpringBoot - 优雅的实现【参数分组校验】高级进阶
SpringBoot - 优雅的实现【参数分组校验】高级进阶
46 0
|
8月前
|
Java 容器 Spring
SpringBoot高级 3
SpringBoot高级
36 1
|
8月前
|
NoSQL Java Redis
SpringBoot高级 2
SpringBoot高级
42 1
|
4月前
|
安全 Java 容器
SpringBoot - 优雅的实现【业务校验】高级进阶
SpringBoot - 优雅的实现【业务校验】高级进阶
81 0
|
4月前
|
Java Spring
SpringBoot - 优雅的实现【自定义参数校验】高级进阶
SpringBoot - 优雅的实现【自定义参数校验】高级进阶
42 0
|
4月前
|
JSON 前端开发 Java
SpringBoot - 优雅的实现【参数校验】高级进阶
SpringBoot - 优雅的实现【参数校验】高级进阶
45 0
|
5月前
|
Java API
SpringBoot【集成ElasticSearch 01】2种方式的高级客户端 RestHighLevelClient 使用(依赖+配置+客户端API测试源码)
SpringBoot【集成ElasticSearch 01】2种方式的高级客户端 RestHighLevelClient 使用(依赖+配置+客户端API测试源码)
88 0
|
5月前
|
Java 关系型数据库 MySQL
Spring Boot使用JdbcTemplate操作mysql数据库实战(附源码 超详细)
Spring Boot使用JdbcTemplate操作mysql数据库实战(附源码 超详细)
42 0
|
5月前
|
前端开发 Java 测试技术
SpringBoot测试——高级配置
SpringBoot测试——高级配置
34 0