spring boot- JdbcTemplate、NamedParameterJdbcTemplate基本使用(批量更新插入)
文章目录
- 第一部分: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();}});}
批量导入注意点:
- sql不要 分号";" 结尾,否则执行报错。它的原理是要字符串连接你这个sql。
- 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中的这些参数可以对批处理语句的速度产生很大影响 – 根据我的经验,它们可以加快速度:
- 增加批量写的速度:
useServerPrepStmts=false
rewriteBatchedStatements=true
useCompression=true - 增加读的速度:
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基本使用(批量更新插入)相关推荐
- spring boot http status 400_kubernetes configmap 热更新spring-boot应用
一. 背景 在生产环境中,一个app服务处于工作中的状态,此时如果需要临时替换某些配置信息,如数据库连接池大小,链接等,一般都需要在源码端修改配置信息,然后重新部署,可想而知,这样做会影响用户或者其他 ...
- Spring Boot 文件通过zip压缩包 批量下载
最近项目中新增了一个需求:要求批量下载之前信息导出的word 文件,也就是批量下载. 数据是保存在ES 中,导出word 的功能也是写好的. 我的思路: 传入数据ID分别导出word 文件到服务器某个 ...
- Spring Boot/Cloud干货汇总(持续更新:20180226版)
抽空对本号推送的Spring相关内容做个汇总整理,包括: - Spring - Spring Boot - Spring cloud - 其他Spring干货内容 Spring Boot专题 基础入门 ...
- Spring Boot JdbcTemplate 入门
原创出处 http://www.iocoder.cn/Spring-Boot/JdbcTemplate/ 「芋道源码」 1. 概述 虽然说,我们现在项目的 DAL 数据访问层,大多使用 MyBatis ...
- SpringBoot----[9]---Spring Boot JdbcTemplate
在pom文件中加入jdbcTemplate的依赖 <dependency><groupId>org.springframework.boot</groupId>&l ...
- Spring Boot JdbcTemplate SQL 查询分页
目录 它是如何运作的 相关文件 分页运行器.java 架构.sql 数据.sql 示例输出 有时,您需要获取的数据量对于单个行程来说太大了.不要害怕,分页是解决这个问题的一种方法. 它是如何运作的# ...
- springboot日志写入mysql_44. Spring Boot日志记录SLF4J【从零开始学Spring Boot】
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看! SpringSecurity5.0视频:http://t.cn/A6ZadMBe Sharding-JDBC分库分表实战: 在开发 ...
- Mysql批量更新的三种方式
前言 批量插入由于mysql的VALUES原生支持,使用较为便利. 批量更新的写法一般有三种,在更新数量较少的情况下,前两种性能不相上下.但是在更新字段增加,更新条数较多(500以上)建议使用第三种写 ...
- Spring Boot 面试题整理
Spring Boot 面试题整理 2018年08月12日 22:32:35 Time_sg 阅读数 19380 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 ...
最新文章
- 调包侠福音!机器学习经典算法开源教程(附参数详解及代码实现)
- 强化学习笔记1:强化学习概述
- zigbee ZIGBEE_FRAGMENTATION
- JDK15新特性密封类可以被继承了!
- TestNG或JUnit
- STM32f4 ARM Bootloader
- php artisan key,Laravel:php artisan key:generate三种报错解决方案,修改默认PHP版本(宝塔面板)...
- Unity插件——Odin使用心得(一)
- 【Typecho插件】SakuraLoad
- 离职前一定要做好这7件事情,少一件都很麻烦。
- 面试时如何回答离开上家公司的原因?
- TiDB2.1 报错statement count 5001 exceeds the transaction limitation, autocommit = false
- 如何解决电脑任务栏无故不见了的问题 ?
- 基于PaddleNLP的中文对话文本匹配
- Codeforces 1148D. Dirty Deeds Done Dirt Cheap
- 世平信息商用密码应用检查系统正式发布!数字时代合规管控路径再突破
- [已解决]为什么使用远程桌面无法打开雷电模拟器,OpenGL版本始终1.1.0?
- linux load average,Linux 平均负载 Load Average 详解
- PIM-SM协议(ASM模型)
- avast! Home/Pro 4.7.1098简体中文
热门文章
- 学习《TensorFlow实战Google深度学习框架 (第2版) 》中文PDF和代码
- 赢得值系列4:Primavera赢得值管理实践
- Python基础入门笔记
- python对excel数据统计_python读取excel数据做分类统计
- spring boot 中 log4j2 日志无法加载(Feature 'http://apache.org/xml/features/xinclude' is not recognized.)
- Latex基本篇章结构
- 黑客利用DDoS造成美国有史以来规模最大的网络攻击,简单来讲就是,交钱不杀。
- 32页精华图解金融业数字化转型发展报告:12大实践特点、4大展望(附PDF下载)
- windows7设置虚拟wifi
- 电子书下载Developing for Google Glass