文章目录

  • 第一部分:JdbcTemplate
    • 一、了解JdbcTemplate
    • 二、JdbcTemplate使用步骤
      • 1. sql直接插入一条数据
      • 2. 通过Statement方式批量插入【推荐】
        • 批量导入 batchUpdate(String sql, BatchPreparedStatementSetter pss)
      • 3. 通过Statement方式批量更新
    • 三、JDBC连接URL中的配置参数(注意配置)
    • 四、jdbctemplate 打印sql配置
    • 五、参考
  • 第二部分: NamedParameterJdbcTemplate
    • 一、查询返回结果映射到自定义类型
      • 使用demo举例
    • 二、queryForList使用时注意事项
  • 第三部分:工作中常见问题整理
    • queryForObject方法返回结果为空会报错
  • 相关参考

第一部分:JdbcTemplate

我们开发DAO层时用的最多的就是ORM框架(Mybatis,hibernate)了。在有些特殊的情况下,ORM框架的搭建略显笨重,这时最好的选择就是Spring中的jdbcTemplate了。

一、了解JdbcTemplate

​ JDBC已经能够满足大部分用户最基本的需求,但是在使用JDBC时,必须自己来管理数据库资源如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。

JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。JdbcTemplate处理了资源的建立和释放。他帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。

JdbcTemplate是原生JDBC的更高一级别的工具性质的操作类,对原生JDBC进行了很多细节上的封装,只提供了入口API,使用者只需要选对API然后传对应的参数即可;将原有的比较繁琐的细节实现屏蔽了,对于使用的角度来说,表现得更加的友好;

jdbcTemplate提供的主要方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

二、JdbcTemplate使用步骤

  • 项目工程是Maven整合SpringBoot2.x进行开发的,所以默认整合了JDBCTemplate, 直接注入导包即可:

1. sql直接插入一条数据

组装sql,直接调用jdbcTemPlate的API即可

private boolean insertBySql() {// 简单的sql执行String sql = "INSERT INTO `money` (`name`, `money`, `is_deleted`) VALUES ('一灰灰blog', 100, 0);";return jdbcTemplate.update(sql) > 0;
}

不推荐这种使用方式,不安全!

2. 通过Statement方式批量插入【推荐】

jdbctemplate的batchUpdate使用方法
参考URL: https://www.cnblogs.com/rookie-ray/p/11790612.html

通过Statement可以指定参数类型,这种插入方式更加安全,有两种常见的方式,注意设置参数时,起始值为1,而不是通常说的0

批量导入 batchUpdate(String sql, BatchPreparedStatementSetter pss)

public int[] batchInsert(List<Book> books) {return this.jdbcTemplate.batchUpdate("insert into books (name, price) values(?,?)",new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement ps, int i) throws SQLException {          ps.setString(1, books.get(i).getName());ps.setBigDecimal(2, books.get(i).getPrice());}@Overridepublic int getBatchSize() {return books.size();}});}

批量导入注意点:

  1. sql不要 分号";" 结尾,否则执行报错。它的原理是要字符串连接你这个sql。
  2. getBatchSize 传进来list大小,setValues里面,根据列表.get(i)获取列表当前遍历的实体类。

返回的int[] it .但是里面的值都是-2 ,-2表示成功。没有具体的行数。

但是从目前测试来看,一条成功,就返回-2, 那么可以用it.length() 记录插入成功多少条记录。
例如,返回结果如: [-2,-2,-2] 代码3条成功!

3. 通过Statement方式批量更新

使用 JdbcTemplate BATCHUPDATE()方法来执行批量插入操作。用这种方法,该语句只被编译一次,执行多次。

    public void batchUpdateByStatement(List<UserPO> updateList) {logger.info("batchUpdateByStatement start! ");String sql = "UPDATE user_check set name=?, code=? where mobile=?";int[] ans = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement preparedStatement, int i) throws SQLException {//注意设置参数时,起始值为1,而不是通常说的0preparedStatement.setString(1, updateList.get(i).getName());preparedStatement.setString(2, updateList.get(i).getCode());preparedStatement.setString(3, updateList.get(i).getMobile());}@Overridepublic int getBatchSize() {return updateList.size();}});logger.info("batchUpdateByStatement success update db size: {}", ans.length);}

如果需要大量更新数据,并且使用的jdbc driver支持batchUpdate的情况下,使用batchUpdate会比直接执行逐行执行update效率快一个数量级。但如果jdbc不支持batchUpdate,那么jdbcTemplate的batchUpdate在其内部仍然是逐行执行。

我使用postgreSQL进行试验:

当需要插入1000个People时,逐行插入需要4秒,使用batchUpdate需要时间不到1秒

当需要插入10000个People时,逐行插入需要17秒,使用batchUpdate仅仅需要1秒

三、JDBC连接URL中的配置参数(注意配置)

db mysql / mysql cluster 5.7.19 / useServerPrepStmts / cachePrepStmts
参考URL: https://www.cnblogs.com/lindows/p/13373347.html

JDBC连接URL中的这些参数可以对批处理语句的速度产生很大影响 – 根据我的经验,它们可以加快速度:

  1. 增加批量写的速度:
    useServerPrepStmts=false
    rewriteBatchedStatements=true
    useCompression=true
  2. 增加读的速度:
    useServerPrepStmts=true
    cachePrepStmts=true

1)useCompression=true,压缩数据传输,优化客户端和MySQL服务器之间的通信性能。
2)rewriteBatchedStatements=true ,开启批量写功能

将会使大批量单条插入语句:

INSERT INTO t (c1,c2) VALUES (‘One’,1);
INSERT INTO t (c1,c2) VALUES (‘Two’,2);
INSERT INTO t (c1,c2) VALUES (‘Three’,3);

改写成真正的批量插入语句:

INSERT INTO t (c1,c2) VALUES (‘One’,1),(‘Two’,2),(‘Three’,3);

3)useServerPrepStmts=false 关闭服务器端编译,sql语句在客户端编译好再发送给服务器端,发送语句如上。

如果为true,sql会采用占位符方式发送到服务器端,在服务器端再组装sql语句。
占位符方式:INSERT INTO t (c1,c2) VALUES (?,?),(?,?),(?,?);

当然我们的目的是为了提高数据库写速度,所以当rewriteBatchedStatements =true时useServerPrepStmts=false必须配合使用。

四、jdbctemplate 打印sql配置

之前用mybaties打印语句很好配置,后来用了JdbcTemplate就不知道怎么打印了,其实JdbcTemplate执行sql语句的过程会做打印sql语句的操作,只不过我们的日志级别没有设置为debug,将自己的日志级别设置为debug就可以了

logging:level:org.springframework.jdbc.core.JdbcTemplate: DEBUG

logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG

五、参考

JdbcTemplate基本使用
参考URL: https://blog.csdn.net/weixin_40001125/article/details/88538576
SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解
参考URL: https://blog.csdn.net/liuyueyi25/article/details/89470146
使用Spring jdbcTemplate的insertOrUpdate操作的最佳实践是什么?
参考URL: https://www.thinbug.com/q/22941655

第二部分: NamedParameterJdbcTemplate

在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定.

在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(named parameter).

那么什么是具名参数?
具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名参数由框架类在运行时用占位符取代
具名参数只在 NamedParameterJdbcTemplate 中得到支持。NamedParameterJdbcTemplate可以使用全部jdbcTemplate方法

NamedParameterJdbcTemplate类拓展了JdbcTemplate类,对JdbcTemplate类进行了封装从而支持命名参数特性。

NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpdate方法。

总结:
开发中尽量使用NamedParameterJdbcTemplate代替JdbcTemplate,如果想使用JdbcTemplate,也可以通过NamedParameterJdbcTemplate#getJdbcOperations()获取。
不建议使用查询结构为Map的API。

一、查询返回结果映射到自定义类型

SpringMVC jdbcTemplate中queryForObject以及queryForList返回映射实体使用
参考URL: https://blog.csdn.net/fengshizty/article/details/43309055

使用BeanPropertyRowMapper + query方法返回自定义对象集合:

List<User> list = new ArrayList();
// 条件查询
String sql = "SELECT * FROM USER WHERE AGE = ?";
// 获取结果
list = jdbcTemplate.query(sql, new Object[]{age}, new BeanPropertyRowMapper<User>(User.class));

其中new Object[]{age}为条件查询,如果查询全量,该字段可以去掉。

使用demo举例

        StringBuffer sqlBuffer = new StringBuffer();sqlBuffer.append("select * from user_info where id = :accountId  ");MapSqlParameterSource sqlParam = new MapSqlParameterSource();sqlParam.addValue("accountId", accountId);BeanPropertyRowMapper<UserVO> rowMapper = new BeanPropertyRowMapper<>(UserVO.class);return jdbcTemplate.query(sqlBuffer.toString(), sqlParam,  rowMapper);

二、queryForList使用时注意事项

SpringBoot中使用JdbcTemplate中queryForList遇到的坑
参考URL: https://blog.csdn.net/HD243608836/article/details/99841903
SpringMVC jdbcTemplate中queryForObject以及queryForList返回映射实体使用
参考URL: https://blog.csdn.net/fengshizty/article/details/43309055

注意使用,使用queryForList只能返回基本类型的集合。

不仅是jdbcTemplate.queryForList不能这么使用,queryForObject同样也不能这么使用,而是应该添加new RowMapper接口才能返回自定义的实体类对象。

使用queryForList返回基本类型的集合<以String为例>:

List<String> names = new ArrayList();
// sql语句,SUBSTR是SQL截取字段的方法,
String sql = "SELECT DISTINCT SUBSTR(NAME, 2) FROM USER ";
// 查询,使用queryForList方法,返回基本类型
names = jdbcTemplate.queryForList(sql, String.class);

注意:映射到自定义类型,我们可以用这个query,不是queryForList

//可以用这个(注意是query,不是queryForList)
List<T> result = jdbcTemplate.query(sql.toString(), new Object[] {queryPara}, new BeanPropertyRowMapper<T>(T.class))

第三部分:工作中常见问题整理

queryForObject方法返回结果为空会报错

关于queryqueryForObject方法返回结果为空会报错及解决方法
参考URL: https://www.pianshen.com/article/65121091946/

问题描述:
问题demo1:
返回的结果是空给我抛了一个异常。

问题demo2:

select  count(b.product_name)  from t_product_code_mapping a, t_asset_info bwhere a.account_id=6and a.service_code = b.service_codegroup by b.product_name
namedJdbcTemplate.queryForObject(sql, sqlParam, Long.class);

当count 搭配group by时,group by 没有查到一个分组时,count的结果就是null。 此时我们queryForObject(sql, sqlParam, Long.class)方法时就会报错。

问题原因:
返回的结果是空给我抛了一个异常。

解决方法:
针对问题demo2,修改sql。 理解其sql,其实它想统计两表联合查询后不同 product_name 的个数。因此 我们 distinct b.product_name 之后,对其进行count 就行。

select  count(distinct b.product_name) as total from t_product_code_mapping a, t_asset_info bwhere a.account_id=8and a.service_code = b.service_code

相关参考

详解jdbcTemplate和namedParameterJdbcTemplate
参考URL: https://www.jianshu.com/p/1bdc0e26a7e4
NamedParameterJdbcTemplate常用方法总结
参考URL: https://blog.csdn.net/u011179993/article/details/74791304
Spring的NamedParameterJdbcTemplate使用方法小结以及项目实战实例
参考URL: https://blog.csdn.net/Jaiaxn/article/details/87889550

spring boot- JdbcTemplate、NamedParameterJdbcTemplate基本使用(批量更新插入)相关推荐

  1. spring boot http status 400_kubernetes configmap 热更新spring-boot应用

    一. 背景 在生产环境中,一个app服务处于工作中的状态,此时如果需要临时替换某些配置信息,如数据库连接池大小,链接等,一般都需要在源码端修改配置信息,然后重新部署,可想而知,这样做会影响用户或者其他 ...

  2. Spring Boot 文件通过zip压缩包 批量下载

    最近项目中新增了一个需求:要求批量下载之前信息导出的word 文件,也就是批量下载. 数据是保存在ES 中,导出word 的功能也是写好的. 我的思路: 传入数据ID分别导出word 文件到服务器某个 ...

  3. Spring Boot/Cloud干货汇总(持续更新:20180226版)

    抽空对本号推送的Spring相关内容做个汇总整理,包括: - Spring - Spring Boot - Spring cloud - 其他Spring干货内容 Spring Boot专题 基础入门 ...

  4. Spring Boot JdbcTemplate 入门

    原创出处 http://www.iocoder.cn/Spring-Boot/JdbcTemplate/ 「芋道源码」 1. 概述 虽然说,我们现在项目的 DAL 数据访问层,大多使用 MyBatis ...

  5. SpringBoot----[9]---Spring Boot JdbcTemplate

    在pom文件中加入jdbcTemplate的依赖 <dependency><groupId>org.springframework.boot</groupId>&l ...

  6. Spring Boot JdbcTemplate SQL 查询分页

    目录 它是如何运作的 相关文件 分页运行器.java 架构.sql 数据.sql 示例输出 有时,您需要获取的数据量对于单个行程来说太大了.不要害怕,分页是解决这个问题的一种方法. 它是如何运作的# ...

  7. springboot日志写入mysql_44. Spring Boot日志记录SLF4J【从零开始学Spring Boot】

    学院中有Spring Boot相关的课程!点击「阅读原文」进行查看! SpringSecurity5.0视频:http://t.cn/A6ZadMBe Sharding-JDBC分库分表实战: 在开发 ...

  8. Mysql批量更新的三种方式

    前言 批量插入由于mysql的VALUES原生支持,使用较为便利. 批量更新的写法一般有三种,在更新数量较少的情况下,前两种性能不相上下.但是在更新字段增加,更新条数较多(500以上)建议使用第三种写 ...

  9. Spring Boot 面试题整理

    Spring Boot 面试题整理 2018年08月12日 22:32:35 Time_sg 阅读数 19380 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 ...

最新文章

  1. 调包侠福音!机器学习经典算法开源教程(附参数详解及代码实现)
  2. 强化学习笔记1:强化学习概述
  3. zigbee ZIGBEE_FRAGMENTATION
  4. JDK15新特性密封类可以被继承了!
  5. TestNG或JUnit
  6. STM32f4 ARM Bootloader
  7. php artisan key,Laravel:php artisan key:generate三种报错解决方案,修改默认PHP版本(宝塔面板)...
  8. Unity插件——Odin使用心得(一)
  9. 【Typecho插件】SakuraLoad
  10. 离职前一定要做好这7件事情,少一件都很麻烦。
  11. 面试时如何回答离开上家公司的原因?
  12. TiDB2.1 报错statement count 5001 exceeds the transaction limitation, autocommit = false
  13. 如何解决电脑任务栏无故不见了的问题 ?
  14. 基于PaddleNLP的中文对话文本匹配
  15. Codeforces 1148D. Dirty Deeds Done Dirt Cheap
  16. 世平信息商用密码应用检查系统正式发布!数字时代合规管控路径再突破
  17. [已解决]为什么使用远程桌面无法打开雷电模拟器,OpenGL版本始终1.1.0?
  18. linux load average,Linux 平均负载 Load Average 详解
  19. PIM-SM协议(ASM模型)
  20. avast! Home/Pro 4.7.1098简体中文

热门文章

  1. 学习《TensorFlow实战Google深度学习框架 (第2版) 》中文PDF和代码
  2. 赢得值系列4:Primavera赢得值管理实践
  3. Python基础入门笔记
  4. python对excel数据统计_python读取excel数据做分类统计
  5. spring boot 中 log4j2 日志无法加载(Feature 'http://apache.org/xml/features/xinclude' is not recognized.)
  6. Latex基本篇章结构
  7. 黑客利用DDoS造成美国有史以来规模最大的网络攻击,简单来讲就是,交钱不杀。
  8. 32页精华图解金融业数字化转型发展报告:12大实践特点、4大展望(附PDF下载)
  9. windows7设置虚拟wifi
  10. 电子书下载Developing for Google Glass