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

文章目录
  1. I. 环境准备
  2. II. 更新使用说明
    1. 1. update 方式
      1. a. 纯sql更新
      2. b. 占位sql
      3. c. statement
    2. 2. batchUpdate 方式
      1. a. 纯sql更新
      2. b. 占位sql
      3. c. statement
    3. 3. 测试
  3. III. 数据删除
  4. IV. 其他
    1. 0. 项目
    2. 1. 一灰灰Blog
    3. 2. 声明
    4. 3. 扫描关注

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

I. 环境准备

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

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

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

data

II. 更新使用说明

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

1. update 方式

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

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

1
2
3
4
5
6
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,执行即可

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

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

1
2
3
4
// 占位方式
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连接,主动设置各种参数

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

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
// 通过 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));

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

show

在上图中,

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

2. batchUpdate 方式

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

1
2
3
4
5
6
7
8
9
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更新

1
2
3
4
5
6
// 批量修改,
// 执行多条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

1
2
3
4
5
// 占位替换方式
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 通过 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,通过一系列的修改,输出如下

test result

III. 数据删除

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

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

IV. 其他

相关博文

0. 项目

1. 一灰灰Blog

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

2. 声明

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

3. 扫描关注

一灰灰blog

QrCode

知识星球

goals


打赏 如果觉得我的文章对您有帮助,请随意打赏。
分享到