Spring Boot 访问数据库——JdbcTemplate

① Spring Boot 框架为 SQL 数据库提供了广泛的支持,既有用 JdbcTemplate 直接访问 JDBC,同时支持“object relational mapping”技术(如 Hibernate、MyBatis)。Spring Data 独立的项目提供对多种关系型和非关系型数据库的访问支持。比如 MySQL、Oracle、MongDB、Redis、R2DBC、Apache Solr、Elasticsearch…
② Spring Boot 也支持嵌入式数据库比如 H2,HSQL,Derby。这些数据库只需要提供 jar 包就能在内存中维护数据。
③ 本篇博客主要讲解如何使用 Spring Boot 中的 JdbcTemplate 访问关系型数据库。

JdbcTemplate

  • 一、配置数据源 DataSource
  • 二、准备数据库环境
  • 三、准备实体类
  • 四、轻量的 JdbcTemplate
    • 1.单条DML语句测试-update方法
    • 2.批量DML语句测试-batchUpdate方法
    • 3.查询一个对象和查询一个值
    • 4.查询多个对象
    • 5.自定义RowMapper
  • 五、NameParameterJdbcTemplate
  • 六、多表查询


一、配置数据源 DataSource

  • DataSourceProperties.java 是数据源的配置类,有那些可以配置的可以参看源码。

    @ConfigurationProperties(prefix = "spring.datasource")
    public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {private ClassLoader classLoader;private boolean generateUniqueName = true;private String name;private Class<? extends DataSource> type;private String driverClassName;private String url;private String username;private String password;private String jndiName;private EmbeddedDatabaseConnection embeddedDatabaseConnection;private Xa xa = new Xa();private String uniqueName;	
    }
    
  • DataSource 在Applicaton 配置文件中以 spring.datasource.* 作为配置项。

    spring:datasource:url: jdbc:mysql://localhost:3306/自己的数据库名username: root(自己的用户名,一般都是root)password: 登录数据库的密码
    
  • Spring Boot 能够从 spring.datasource.url 推断所使用的数据驱动类,如果需要特殊指定请设置 spring.datasource.driverClassName 为驱动类的全限定名称。

  • Spring Boot 支持多种数据库连接池,优先使用 HikariCP,其次是 Tomcat pooling,再次是 Commons DBCP2,如果以上都没有,最后使用 Oracle UCP 连接池。当项目中 starter 依赖了 spring-boot-starter-jdbc 或者 spring-boot-stater-data-jpa 默认添加 HikariCP 连接池依赖,也就是默认使用 HikariCP 连接池。


二、准备数据库环境

  • 访问数据库先准备数据库的 script。SpringBoot 能够自动执行 DDL,DML 脚本。两个脚本文件名称默认是 schema.sql 和 data.sql。脚本文件在类路径中自动加载。
  • 自动执行脚本使用配置项 spring.sql.inti.mode 配置项
    • always 表示Spring Boot应用启动时始终执行数据库初始化
    • embedded 表示只初始化内存数据库,比如 H2 数据库
    • never 表示从不执行初始化数据库
    # schema.sql 文件
    DROP TABLE IF EXISTS `article`;
    CREATE TABLE `article`
    (`id`          int                                                           NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id`     int                                                           NOT NULL COMMENT '作者 ID',`title`       varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文章标题',`summary`     varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文章概要',`read_count`  int(11) UNSIGNED ZEROFILL                                     NOT NULL COMMENT '阅读读数',`create_time` datetime                                                      NOT NULL COMMENT '创建时间',`update_time` datetime                                                      NOT NULL COMMENT '最后修改时间',PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDBAUTO_INCREMENT = 1CHARACTER SET = utf8mb4COLLATE = UTF8MB4_0900_AI_CIROW_FORMAT = Dynamic;DROP TABLE IF EXISTS `article_detail`;
    CREATE TABLE `article_detail`
    (`id`         int                                                   NOT NULL AUTO_INCREMENT COMMENT '注解',`article_id` int                                                   NOT NULL COMMENT '文章 ID',`content`    text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文章内容',PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDBAUTO_INCREMENT = 1CHARACTER SET = utf8mb4COLLATE = utf8mb4_0900_ai_ciROW_FORMAT = Dynamic;
    
    # data.sql 文件
    -- ----------------------------
    -- Records of article
    -- ----------------------------
    INSERT INTO `article`
    VALUES (1, 2101, 'SpringBoot 核心注解', '核心注解的主要作用', 00000008976, '2023-01-16 12:11:12','2023-01-16 12:11:19');
    INSERT INTO `article`
    VALUES (2, 356752, 'JVM 调优', 'HotSpot 虚拟机详解', 00000000026, '2023-01-16 12:15:27', '2023-01-16 12:15:30');-- ----------------------------
    -- Records of article_detail
    -- ----------------------------
    INSERT INTO `article_detail`
    VALUES (1, 1, '注解十分的重要,例如:SpringBootApplication');
    
  • Spring Boot 处理特定的数据库类型,为特定的数据库定制 script 文件。首先设置 spring.sql.init.platform = hsqdb、h2、Oracle、postgresql 等等,其次准备 schema-${platform}.sql、data-${platform}.sql 脚本文件。

三、准备实体类

public class ArticleDetail {private Integer id;private Integer userId;private String summary;private String title;private Integer readCount;private LocalDateTime createTime;private LocalDateTime updateTime;//全参构造、无参构造、toString、set和get方法
}
public class ArticleDetail {private Integer id;private Integer articleId;private String content;//全参构造、无参构造、toString、set和get方法
}

四、轻量的 JdbcTemplate

//Jdbc绑定Bean的源码
@ConfigurationProperties(prefix = "spring.jdbc")
public class JdbcProperties {private final Template template = new Template();public Template getTemplate() {return this.template;}public static class Template {/*** Number of rows that should be fetched from the database when more rows are* needed. Use -1 to use the JDBC driver's default configuration.*/private int fetchSize = -1;/*** Maximum number of rows. Use -1 to use the JDBC driver's default configuration.*/private int maxRows = -1;/*** Query timeout. Default is to use the JDBC driver's default configuration. If a* duration suffix is not specified, seconds will be used.*/@DurationUnit(ChronoUnit.SECONDS)private Duration queryTimeout;}
}
  • 项目中依赖了 spring-jdbc,JdbcTemplate 对象会自动创建好。把 JdbcTemplate 对象注入给你的 Bean,再调用 JdbcTemplate 的方法执行查询,更新,删除的SQL。
  • JdbcTemplate 上手快,功能非常强大。提供了丰富、实用的方法,归纳起来主要有以下几种类型的方法:
    • execute 方法:可以用于执行任何的 SQL 语句,常用来执行 DDL 语句。
    • upate、batchUpdate 方法:用于 DML 语句。
    • query 和 queryForXXX 方法:用于执行 DQL 语句。
    • call 方法:用于执行数据库存储过程和函数相关语句。

1.单条DML语句测试-update方法

  • update方法有两个参数:
    • 第一个参数:要执行的SQL语句。(SQL语句中可能会有占位符 ? )
    • 第二个参数:可变长参数,参数的个数可以是0个,也可以是多个。一般是SQL语句中有几个问号,则对应几个参数。
@SpringBootTest
class JdbcTemplateApplicationTests {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testvoid insert() {String sql = "insert into article_detail (article_id, content) values (?, ?)";int count = jdbcTemplate.update(sql, 2, "JVM 十分的重要,一定要去学习。");System.out.println("插入的记录条数是:" + count);}@Testvoid modify() {String sql = "update article_detail set content = ? where id = ?";int count = jdbcTemplate.update(sql, "Spring Boot 中的核心注解十分重要", 2);System.out.println("修改的记录条数是:" + count);}@Testvoid delete() {String sql = "delete  from article_detail where id = ?";int count = jdbcTemplate.update(sql, 2);System.out.println("删除的记录条数是:" + count);}}

2.批量DML语句测试-batchUpdate方法

@SpringBootTest
class JdbcTemplateApplicationTests {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testvoid batchInsert() {String sql = "insert into article_detail (article_id, content) values (?, ?)";Object[] obj1 = {2, "JVM 十分的重要,一定要去学习。"};Object[] obj2 = {1, "SpringBoot 十分的重要,一定要去学习。"};Object[] obj3 = {2, "JVM 学习了之后一定会大有收获的"};List<Object[]> list = new ArrayList<>();list.add(obj1);list.add(obj2);list.add(obj3);int[] count = jdbcTemplate.batchUpdate(sql, list);System.out.println("插入的记录条数是:" + Arrays.toString(count));}@Testvoid batchModify() {String sql = "update article_detail set content = ? where id = ?";Object[] obj1 = {"测试更新", 4};Object[] obj2 = {"测试更新", 5};Object[] obj3 = {"测试更新", 3};List<Object[]> list = new ArrayList<>();list.add(obj1);list.add(obj2);list.add(obj3);int[] count = jdbcTemplate.batchUpdate(sql, list);System.out.println("更新的记录条数是:" + Arrays.toString(count));}@Testvoid batchDelete() {String sql = "delete from article_detail where id = ?";Object[] obj1 = {4};Object[] obj2 = {5};Object[] obj3 = {3};List<Object[]> list = new ArrayList<>();list.add(obj1);list.add(obj2);list.add(obj3);int[] count = jdbcTemplate.batchUpdate(sql, list);System.out.println("删除的记录条数是:" + Arrays.toString(count));}
}

3.查询一个对象和查询一个值

  • queryForObject方法三个参数:
    • 第一个参数:sql语句
    • 第二个参数:Bean属性值和数据库记录行的映射对象。在构造方法中指定映射的对象类型。
    • 第三个参数:可变长参数,给sql语句的占位符问号传值。
  • 这个方法查询出来的结果只能是一个数据,如果多于一个数据或者没有查询到数据就会报错。
@SpringBootTest
class JdbcTemplateApplicationTests {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testvoid queryOneObject(){String sql = "select * from article where id = ?";Article article = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Article.class), 1);System.out.println(article);}@Testvoid queryOneOValue(){String sql = "select count(*) from article";Long count = jdbcTemplate.queryForObject(sql, Long.class);System.out.println("查询到的记录条数 =====> " + count);}
}

4.查询多个对象

@SpringBootTest
class JdbcTemplateApplicationTests {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testvoid queryMulObject(){String sql = "select * from article";List<Article> articles = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Article.class));System.out.println(articles);}
}

5.自定义RowMapper

@SpringBootTest
class JdbcTemplateApplicationTests {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testvoid testQueryRowMapper() {String sql = "select * from article where id = 1";Article article = jdbcTemplate.execute(sql, new PreparedStatementCallback<Article>() {@Overridepublic Article doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {Article article = null;ResultSet rs = ps.executeQuery();if (rs.next()) {var id = rs.getInt("id");var userId = rs.getInt("user_id");var title = rs.getString("title");var summary = rs.getString("summary");var readCount = rs.getInt("read_count");var createTime = new Timestamp(rs.getTimestamp("create_time").getTime()).toLocalDateTime();var updateTime = new Timestamp(rs.getTimestamp("update_time").getTime()).toLocalDateTime();article = new Article(id, userId, summary, title, readCount, createTime, updateTime);}return article;}});System.out.println(article);}
}

五、NameParameterJdbcTemplate

  • NameParameterJdbcTemplate 能够接受命名的参数,通过具名的参数提供代码的可读性。NameParameterJdbcTemplate 使用的是参数索引的方式。

  • 在使用模板的位置上注入 NameParameterJdbcTemplate 对象,编写 SQL 语句,在 SQL 中Where 部分“:命名参数”。调用 NameParameterJdbcTemplate 的诸如 query,queryForObject,execute,update等时,将参数封装到 Map 中。

    @SpringBootTest
    class JdbcTemplateApplicationTests {@Autowiredprivate NamedParameterJdbcTemplate namedParameterJdbcTemplate;@Testvoid testNameQuery(){String sql = "select count(*) as ct from article where user_id = :uid and read_count > :num";Map<String, Object> map = new HashMap<>();map.put("uid", 2101);map.put("num", 0);Long count = namedParameterJdbcTemplate.queryForObject(sql, map, Long.class);System.out.println(count);}
    }
    

六、多表查询

  • 多表查询关注的是查询结果如何映射为 Java Object。常用两种方案:
    • 第一种是将查询结果转化为Map。key是列名,value是列值,这种方式比较通用,适合查询任何表。
    @SpringBootTest
    class JdbcTemplateApplicationTests {@Autowiredprivate NamedParameterJdbcTemplate namedParameterJdbcTemplate;@Testvoid testNameQuery(){String sql = "select a.*, d.content from article a join article_detail d on a.id = d.article_id where a.id = :id";Map<String, Object> param = new HashMap<>();param.put("id", 1);Map<String, Object> objectMap = namedParameterJdbcTemplate.queryForMap(sql, param);objectMap.forEach(( key, value)->{System.out.println(key + "---->" + value);});}
    }
    
    • 第二种是根据查询结果中包含的列,创建相应的实体类。属性和查询结果的列对应。
    	@SpringBootTest
    class JdbcTemplateApplicationTests {@Autowiredprivate NamedParameterJdbcTemplate namedParameterJdbcTemplate;@Testvoid testNameQuery(){String sql = "select a.*, d.content from article a join article_detail d on a.id = d.article_id where a.id = :id";Map<String, Object> param = new HashMap<>();param.put("id", 1);ArticleAndDetail articleAndDetail = namedParameterJdbcTemplate.queryForObject(sql, param, new BeanPropertyRowMapper<>(ArticleAndDetail.class));System.out.println(articleAndDetail);}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/650891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE中,跳转页面之前判断并显示弹框组件

VUE中&#xff0c;跳转页面之前判断并显示弹框组件。 涉及到路由守卫、数据交互。有空我在完善&#xff0c;先直接给出代码 代码使用了 element plus、vuex 案例代码 路由文件 import { createRouter, createWebHistory } from vue-router; import CommonEntry from /views/…

取消Vscode在输入符号时自动补全

取消Vscode在输入符号时自动补全 取消Vscode在输入符号时自动补全问题演示解决方法 取消Vscode在输入符号时自动补全 问题演示 在此状态下输入/会直接自动补全, 如下图 笔者想要达到的效果为可以正常输入/而不进行补全, 如下图 解决方法 在设置->文本编辑器->建议, 取消…

以太网的 MAC 层

目录 1. MAC 层的硬件地址 48 位的 MAC 地址 2. MAC 帧的格式 以太网 V2 的 MAC 帧格式 无效的 MAC 帧 IEEE 802.3 MAC 与以太网 V2 MAC 帧格式的区别 1. MAC 层的硬件地址 硬件地址又称为物理地址&#xff0c;或 MAC 地址。 IEEE 802 标准为局域网规定了一种 48 位…

Acwing801二进制中1的个数

题目 给定一个长度为 n 的数列&#xff0c;请你求出数列中每个数的二进制表示中 11 的个数。 输入格式: 第一行包含整数 n 第二行包含 n 个整数&#xff0c;表示整个数列。 输出格式: 共一行&#xff0c;包含 n 个整数&#xff0c;其中的第 i 个数表示数列中的第 i 个数的…

HTML你要知道哪些语法?

表格 表格的主要作用 1.表格主要用于显示、展示数据&#xff0c;因为它可以让数据显示的非常的规整&#xff0c;可读性非常好。特别是后台展示数据的时候&#xff0c;能够熟练运用表格就显得很重要。一个清爽简约的表格能够把繁杂的数据表现得很有条理 2.表格不是用来布局页…

【Kafka】高级特性:主题

目录 主题的管理创建主题查看主题修改主题删除主题 增加分区分区副本的分配必要参数配置KafkaAdminClient应用功能操作示例 主题的管理 使用kafka-topics.sh脚本。 下面是使用脚本的一些选项 选项说明–config <String: namevalue>为创建的或修改的主题指定配置信息。…

C语言常见面试题:什么是枚举,枚举的作用是什么?

枚举是一种特殊的数据类型&#xff0c;它是一组具命名的整型常量的集合。枚举的作用如下&#xff1a; 限制用户不能随意赋值&#xff1a;枚举类型可以限制用户只能使用定义时列举的值进行赋值&#xff0c;而不能随意赋值。这样可以增加代码的可读性和可维护性。方便管理公共的…

[题单练习] 大模拟题

看完题后不知所措 P1058 [NOIP2008 普及组] 立体图 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 简单来说&#xff0c;题目要我们按照输入&#xff0c;把立体图画出来&#xff0c;先放张图来震撼一下 看题解&#xff0c;题解的思路如下&#xff1a; 1. 先把一个积木块存入…

栈和队列的动态实现(C语言实现)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

图像与二进制数据间的转换

概述 此文档主要是记录图像与二进制互相转换的方法&#xff0c;此文档记录于20220811 进行图片和二进制的互相转换 若想转为base64&#xff0c;可以看 图像与base64互转 的内容。 Python 资料&#xff1a;python 图片和二进制转换的三种方式_脸不大的CVer的博客-CSDN博客_p…

统计学-R语言-7.3

文章目录 前言总体方差的检验一个总体方差的检验两个总体方差比的检验 非参数检验总体分布的检验正态性检验的图示法Shapiro-Wilk和K-S正态性检验总体位置参数的检验 练习 前言 本篇文章继续对总体方差的检验进行介绍。 总体方差的检验 一个总体方差的检验 在生产和生活的许多…

1 月 26日算法练习

文章目录 九宫幻方穿越雷区走迷宫 九宫幻方 小明最近在教邻居家的小朋友小学奥数&#xff0c;而最近正好讲述到了三阶幻方这个部分&#xff0c;三阶幻方指的是将1~9不重复的填入一个33的矩阵当中&#xff0c;使得每一行、每一列和每一条对角线的和都是相同的。 三阶幻方又被称…

IS-IS:07 ISIS缺省路由

IS-IS 有两种缺省路由&#xff0c;第一种缺省路由是由 level-1 路由器在特定条件下自动产生的&#xff0c;它的下一跳是离它最近的 &#xff08;cost 最小&#xff09;level-1-2路由器。第二种缺省路由是 IS-IS 路由器上使用 default-route-advertise 命令产生并发布的。 本次实…

第十七讲_HarmonyOS应用开发Stage模型应用组件

HarmonyOS应用开发Stage模型应用组件 1. 应用级配置2. Module级配置3. Stage模型的组件3.1 AbilityStage3.1.1 AbilityStage的创建和配置3.1.2 AbilityStage的生命周期回调3.1.3 AbilityStage的事件回调&#xff1a; 3.2 UIAbility3.2.1 UIAbility生命周期3.2.3 UIAbility启动模…

CSAPP fall2015 深入理解计算机系统 Cache lab详解

Cache Lab cache lab 缓存实验 代码下载 从CSAPP上面下载对应的lab代码 http://csapp.cs.cmu.edu/3e/labs.html 环境准备 需要安装 valgrind。可以参考文章Valgrind centos。 安装好以后执行valgrind --version可以看到版本号。 Cache simulator cache simulator not a …

ART: Automatic multi-step reasoning and tool-use for large language models 导读

ART: Automatic multi-step reasoning and tool-use for large language models 本文介绍了一种名为“自动推理和工具使用&#xff08;ART&#xff09;”的新框架&#xff0c;用于解决大型语言模型&#xff08;LLM&#xff09;在处理复杂任务时需要手动编写程序的问题。该框架可…

【音视频原理】音频编解码原理 ③ ( 音频 比特率 / 码率 | 音频 帧 / 帧长 | 音频 帧 采样排列方式 - 交错模式 和 非交错模式 )

文章目录 一、音频 比特率 / 码率1、音频 比特率2、音频 比特率 案例3、音频 码率4、音频 码率相关因素5、常见的 音频 码率6、视频码率 - 仅做参考 二、音频 帧 / 帧长1、音频帧2、音频 帧长度 三、音频 帧 采样排列方式 - 交错模式 和 非交错模式1、交错模式2、非交错模式 一…

排序问题上机考试刷题

排序与查找可以说是计算机领域最经典的问题&#xff0c;排序和查找问题在考研机试真题中经常出现。排序考点在历年机试考点中分布广泛。排序既是考生必须掌握的基本算法&#xff0c;又是考生 学习其他大部分算法的前提和基础。首先学习对基本类型的排序。对基本类型排序&#x…

【C++中的STL】函数对象

函数对象 函数对象概念谓词概念 内建函数对象算术仿函数关系仿函数逻辑仿函数&#xff08;基本用不到&#xff09; 函数对象概念 重载函数调用操作符的类&#xff0c;其对象常称为函数对象&#xff0c;函数对象使用重载的()时。行为类似函数调用&#xff0c;也叫仿函数。 函数…

分析crash日志

每一天都要快乐的进步~~ 文章目录 在分析 crash 日志时&#xff0c;通常需要关注以下信息&#xff1a; 1️⃣ 错误信息&#xff1a;了解 crash 的具体错误信息&#xff0c;这有助于定位问题的根源所在。 2️⃣ 堆栈跟踪&#xff1a;查看堆栈跟踪&#xff0c;确定 crash 发生的…