一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

    • H2Database

    • JPA

    • JdbcTemplate

      • 【DB系列】JdbcTemplate之数据插入使用姿势详解
      • 【DB系列】JdbcTemplate之数据查询上篇
      • 【DB系列】JdbcTemplate之数据查询下篇
      • 【DB系列】JdbcTemplate之数据更新与删除
        • I. 环境准备
        • II. 更新使用说明
          • 1. update 方式
          • 2. batchUpdate 方式
          • 3. 测试
        • III. 数据删除
        • IV. 其他
          • 0. 项目
          • 1. 一灰灰Blog
          • 2. 声明
          • 3. 扫描关注
      • 【DB系列】JdbcTemplate之多数据源配置与使用
    • Jooq

    • Mybatis

    • 事务

    • MongoDB

    • Redis

    • 实例

  • 搜索系列

  • MQ系列

  • WEB系列

  • 中间件

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • DB系列
  • JdbcTemplate
一灰灰
2019-04-18

【DB系列】JdbcTemplate之数据更新与删除

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

# I. 环境准备

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

或者直接查看项目源码: https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/101-jdbctemplate (opens new window)

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

data

# 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);
}
1
2
3
4
5
6

# 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));
1
2
3
4
5
6

# 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));
1
2
3
4

# 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));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

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

show

在上图中,

  • 首先是一个开启一个事物,并修改了一条记录,这个时候这条记录会加上写锁
  • 然后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));
}
1
2
3
4
5
6
7
8
9

# 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)));
1
2
3
4
5
6

# 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)));
1
2
3
4
5

# 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)));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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

# 3. 测试

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

test result

# 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);
    }
}
1
2
3
4
5
6
7
8
9
10

# IV. 其他

相关博文

  • 190407-SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解 (opens new window)
  • 190412-SpringBoot高级篇JdbcTemplate之数据查询上篇 (opens new window)
  • 190417-SpringBoot高级篇JdbcTemplate之数据查询下篇 (opens new window)

# 0. 项目

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 项目:https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/101-jdbctemplate (opens new window)

# 1. 一灰灰Blog

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

# 2. 声明

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

  • 微博地址: 小灰灰Blog (opens new window)
  • QQ: 一灰灰/3302797840

# 3. 扫描关注

一灰灰blog

QrCode

知识星球

goals

编辑 (opens new window)
#JdbcTemplate#DB
上次更新: 2021/10/15, 19:56:22
【DB系列】JdbcTemplate之数据查询下篇
【DB系列】JdbcTemplate之多数据源配置与使用

← 【DB系列】JdbcTemplate之数据查询下篇 【DB系列】JdbcTemplate之多数据源配置与使用→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×