Spring 数据库编程
Spring JDBC
传统的JDBC在操作数据库时,需要先打开数据库连接,执行SQL语句,然后封装结果,最后关闭数据库连接等资源。频繁的数据库操作会产生大量的重复代码,造成代码冗余,Spring的JDBC模块负责数据库资源管理和错误处理,大大简化了开发人员对数据库的操作,使开发人员可以从频繁的数据库操作中解脱出来,从而将更多的精力投入编写业务逻辑中。
JdbcTemplate
针对数据库操作,Spring框架提供了JdbcTemplate类,JdbcTemplate是一个模板类,Spring JDBC中的更高层次的抽象类均在JdbcTemplate模板类的基础上创建。
JdbcTemplate类提供了操作数据库的基本方法,包括添加、删除、查询和更新。在操作数据库时,JdbcTemplate类简化了传统JDBC中的复杂步骤,这可以让开发人员将更多精力投入到业务逻辑中。
JdbcTemplate类继承自抽象类JdbcAccessor,同时实现了JdbcTemplate接口。抽象类JdbcAccessor提供了一些访问数据库时使用的公共属性,具体如下:
- DataSource:DataSource主要功能是获取数据库连接。在具体的数据操作中,它还提供对数据库连接的缓冲池和分布式事务的支持。
- SQLExceptionTranslator:SQLExceptionTranslator是一个接口,它负责对SQLException异常进行转译工作。
Spring JDBC的配置
Spring JDBC中的4个包说明:
| 包名 | 说明 |
|---|---|
| core(核心包) | 包含了JDBC的核心功能,包括JdbcTemplate类、SimpleJdbcInsert类、SimpleJdbcCall类以及NamedParameterJdbcTemplate类。 |
| dataSource(数据源包) | 包含访问数据源的实用工具类,它有多种数据源的实现,可以在Java EE容器外部测试JDBC代码。 |
| object(对象包) | 以面向对象的方式访问数据库,它可以执行查询、修改和更新操作并将返回结果作为业务对象,并且在数据表的列和业务对象的属性之间映射查询结果。 |
| support(支持包) | 包含了core和object包的支持类,如提供异常转换功能的SQLException类。 |
Spring对数据库的操作都封装在了core、dataSource、object和support这4个包中,想要使用Spring JDBC,就需要对这些包进行配置。在Spring中,JDBC的配置是在配置文件applicationContext.xml中完成的。
配置数据源:包括数据库驱动、连接数据库url、连接数据库用户名、连接数据库密码。
<bean id="dataSource" class=
"org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- 数据库驱动 --><property name="driverClassName" value="com.mysql.jdbc.Driver"/><!-- 连接数据库url --><property name="url" value="jdbc:mysql://localhost:3306/spring"/><property name="username" value="root"/><!-- 连接数据库用户名 --><property name="password" value="root"/><!-- 连接数据库密码 -->
</bean>
配置JDBC模板:必须使用默认数据源。
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 默认必须使用数据源 --><property name="dataSource" ref="dataSource"/>
</bean>
配置注入类
<bean id="xxx" class="Xxx"><property name="JdbcTemplate" ref="JdbcTemplate"/>
</bean>
dataSource配置的4个属性:
| 属性名 | 含义 |
|---|---|
| driverClassName | 所使用的驱动名称,对应驱动JAR包中的Driver类 |
| url | 数据源地址 |
| username | 访问数据库的用户名 |
| password | 访问数据库的密码 |
dataSource属性值的设定要求
在dataSource的4个属性中,需要根据数据库类型或者系统配置设置相应的属性值。例如,如果数据库类型不同,需要更改驱动名称;如果数据库不在本地,则需要将地址中的localhost替换成相应的主机IP;默认情况下,数据库端口号可以省略,但如果修改过MySQL数据库的端口号,则需要加上修改后的端口号。此外,连接数据库的用户名和密码需要与数据库创建时设置的用户名和密码保持一致。
接下来,我们通过JDBCTemplate的实现数据库的增删改查操作
首先实现数据库的配置如下:
<!-- 数据源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/></bean><!-- 配置jdbc模板 JdbcTemplate --><bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!-- 配置注入类 --><bean id="user" class="com.lq.entities.User"><property name="JdbcTemplate" ref="JdbcTemplate"/></bean>
创建项目,目录如下:
在pom文件里添加maven依赖,我们特意引入了spring-jdbc和mysql-connector-java依赖,为了实现jdbc操作。
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>6.1.16</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version><scope>test</scope></dependency><!-- jdbc包依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.7</version></dependency><!-- 事务管理依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.3.7</version></dependency><!-- 数据库驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency>
创建实体类Account
package com.lq.entities;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: Account* @Version: 1.0*/public class Account {private int id;private String username;private Double balance;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}@Overridepublic String toString() {return "Account{" +"id=" + id +", username='" + username + '\'' +", balance=" + balance +'}';}
}
创建接口AccountDao
package com.lq.dao;import com.lq.entities.Account;import java.util.List;/*** @Author: lzq* @CreateTime: 2025-02-27* @Description: AccountDao* @Version: 1.0*/public interface AccountDao {public int addAccount(Account account);public int updateAccount(Account account);public int deleteAccount(int id);public Account findAccountById(int id);public List<Account> findAllAccount();
}
增删改查的接口实现:
package com.lq.dao.impl;import com.lq.dao.AccountDao;
import com.lq.entities.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;import java.util.List;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: 实现类* @Version: 1.0*/public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic int addAccount(Account acc) {String sql = "INSERT INTO account (username, balance) VALUES (?, ?)";Object[] obj = new Object[]{acc.getUsername(),acc.getBalance()};int result = this.jdbcTemplate.update(sql, obj);return result;}@Overridepublic int updateAccount(Account account) {String sql = "update account set username=?,balance=? where id=?";Object[] obj = new Object[]{account.getUsername(),account.getBalance(),account.getId()};int result = jdbcTemplate.update(sql, obj);return result;}@Overridepublic int deleteAccount(int id) {String sql = "delete from account where id=?";int result = jdbcTemplate.update(sql, id);return result;}@Overridepublic Account findAccountById(int id) {String sql = "select * from account where id=?";//创建一个新的BeanPropertyRowMapper对象RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);//将id绑定到sql中,并且将查询结果封装到Account对象中Account account = this.jdbcTemplate.queryForObject(sql, rowMapper, id);return account;}@Overridepublic List<Account> findAllAccount() {String sql = "select * from account";RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);List<Account> accounts = this.jdbcTemplate.query(sql, rowMapper);return accounts;}
}
本案例的Spring配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 数据源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/springjdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/></bean><!-- 配置jdbc模板 JdbcTemplate --><bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean id="accountDao" class="com.lq.dao.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="JdbcTemplate"/></bean></beans>
接下来进行测试:
package com.lq.test;import com.lq.dao.AccountDao;
import com.lq.entities.Account;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;import java.lang.annotation.Target;
import java.util.List;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: jdbcTest* @Version: 1.0*/public class JdbcTest {@Testpublic void test1(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) app.getBean("JdbcTemplate");jdbcTemplate.execute("" +"create table account("+ "id int primary key auto_increment,"+"username varchar(50),"+"balance double)");System.out.println("创建成功");}@Testpublic void test2(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = new Account();account.setUsername("肖炎");account.setBalance(1000.0);int res = accountDao.addAccount(account);if(res>0){System.out.println("成功添加了"+res+"条数据");}else{System.out.println("添加失败");}}@Testpublic void test3(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = new Account();account.setId(1);account.setUsername("小医仙");account.setBalance(1500.0);int res = accountDao.updateAccount(account);if(res>0){System.out.println("成功修改了"+res+"条数据");}else{System.out.println("修改失败");}}@Testpublic void test4(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");int res = accountDao.deleteAccount(1);if(res>0){System.out.println("成功删除了"+res+"条数据");}else{System.out.println("删除失败");}}@Testpublic void test5(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = accountDao.findAccountById(2);System.out.println(account);System.out.println("------------------------");List<Account> allAccount = accountDao.findAllAccount();for (Account account1 : allAccount) {System.out.println(account1);}}
}
JdbcTemplate类中常用的查询方法
| 方法 | 说明 |
|---|---|
| List query(Stringsql,RowMapper rowMapper) | 执行String类型参数提供的SQL语句,并通过参数rowMapper返回一个List类型的结果。 |
| List query(Stringsql, PreparedStatementSetter pss, RowMapper rowMapper) | 根据String类型参数提供的SQL语句创建PreparedStatement对象,通过参数rowMapper将结果返回到List中。 |
| List query(Stringsql, Object[]args, RowMapper rowMapper) | 使用Object[]的值来设置SQL语句中的参数值,rowMapper是个回调方法,直接返回List类型的数据。 |
| queryForObject(Stringsql, RowMapper rowMapper, Object…args) | 将args参数绑定到SQL语句中,并通过参数rowMapper返回一个Object类型的单行记录。 |
| queryForList(Stringsql,Object[]args, class<T>elementType) | 该方法可以返回多行数据的结果,但必须返回列表,args参数是sql语句中的参数,elementType参数返回的是List数据类型。 |
相关文章:
Spring 数据库编程
Spring JDBC 传统的JDBC在操作数据库时,需要先打开数据库连接,执行SQL语句,然后封装结果,最后关闭数据库连接等资源。频繁的数据库操作会产生大量的重复代码,造成代码冗余,Spring的JDBC模块负责数据库资源…...
进阶篇|CAN FD 与性能优化
引言 1. CAN vs. CAN FD 对比 2. CAN FD 帧结构详解...
CTF--各种绕过哟
一、原网页: 二、步骤: 1.源代码: <?php highlight_file(flag.php); $_GET[id] urldecode($_GET[id]); $flag flag{xxxxxxxxxxxxxxxxxx}; if (isset($_GET[uname]) and isset($_POST[passwd])) {if ($_GET[uname] $_POST[passwd])pr…...
【Pandas】pandas DataFrame where
Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行DataFrame.at快速访问和修改 DataFrame 中单个值的方法DataFrame.iat快速访问和修改 DataFrame 中单个值的方法DataFrame.loc用于基于标签(行标签和列标签&#…...
嵌入式ARM RISCV toolchain工具 梳理arm-none-eabi-gcc
嵌入式TOOLchain工具 梳理 简介 本文总结和梳理一下一些toolchain的规则和原理,方便后续跨平台的时候,给大家使用toolchain做一个参考。 解释如何理解arm-none-eabi-gcc等含义,以及如何一看就知道该用什么编译器。 当然如果有哪里写的不是…...
OpenBMC:BmcWeb log输出
BmcWeb的log函数定义于:http\logging.hpp 说实话,个人觉得这一版的log函数有点炫技,使用起来也没有之前的版本方便,不过也还是值的参考一下。 1.如何输出log BMCWEB_LOG_ERROR("GetAll on path {} iface {} service {} failed with code {}",objectPath, inte…...
复现SCI图像增强(Toward fast, flexible, and robust low-light image enhancement.)
运行train.py报错 > File "/home/uriky/桌面/SCI-main/SCI-main/train.py", line 105, in main > train_queue torch.utils.data.DataLoader( File "/home/uriky/anaconda3/envs/AA/lib/python3.8/site-packages/torch/utils/data/dataloader.py&q…...
深入理解C++中string的深浅拷贝
目录 一、引言 二、浅拷贝与深拷贝的基本概念 2.1 浅拷贝 2.2 深拷贝 在C 中, string 类的深浅拷贝有着重要的区别。 浅拷贝 深拷贝 string 类中的其他构造函数及操作 resize 构造 构造(赋值构造) 构造(拼接构造…...
性能测试面试题的详细解答
以下是性能测试面试题的详细解答: 1. 性能测试的流程是怎样的? 性能测试流程通常包括以下几个步骤: - **需求分析**:明确测试目标、性能指标(如响应时间、吞吐量等)。 - **环境搭建**:搭建测试环…...
第八篇:系统分析师第三遍——3、4章
目录 一、目标二、计划三、完成情况四、意外之喜(最少2点)1.计划内的明确认知和思想的提升标志2.计划外的具体事情提升内容和标志 五、总结 一、目标 通过参加考试,训练学习能力,而非单纯以拿证为目的。 1.在复习过程中,训练快速阅读能力、掌…...
Unity粒子特效打包后不显示
1.粒子发mesh,如果打包后不显示,尝试勾选r/w 2.如果还不行,mesh重做,目前发现ab包打出的,有的mesh会出问题,暂时原因不详。...
PFC 是什么?
现在进行液晶电视机和等离子电视机电路分析时、故障维修时,都经常的提到“PFC 电路”一词,这 在早期的电视机中是没有的,早期维修电视机的师傅从来没有接触过的,但是 PFC 电路是目前液晶电视机 和等离子电视机中不可缺少的电路。那…...
6.5 GitHub监控系统实战:双通道采集+动态调度打造高效运维体系
GitHub Sentinel Agent 定期更新功能设计与实现 关键词:GitHub API 集成、定时任务调度、Python 爬虫开发、SMTP 邮件通知、系统稳定性保障 1. GitHub 项目数据获取功能 1.1 双通道数据采集架构设计 #mermaid-svg-ZHJIMXcMAyDHVhmV {font-family:"trebuchet ms",v…...
楼梯上下检测数据集VOC+YOLO格式5462张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):5462 标注数量(xml文件个数):5462 标注数量(txt文件个数):5462 …...
消防营区管控:从智能仓储、装备管理、应急物资调用等多维度出发
近期,一系列消防安全热点事件引发了社会各界的广泛关注。某老旧城区的一场火灾,由于消防通道被杂物堵塞,消防车辆无法及时靠近火源,加之周边消防设施老化,灭火物资储备不足,导致火势迅速蔓延,造…...
Flutter 自定义插件基础
1、Flutter插件是什么?官方插件库 在开发Flutter应用过程中会涉及到平台相关接口调用,例如数据库操作、相机调用、外部浏览器跳转等业务场景。其实Flutter自身并不支持直接在平台上实现这些功能,而是通过插件包接口去调用指定平台API从而实现…...
解锁古籍中的气候密码,探索GPT/BERT在历史灾害研究中的前沿应用;气候史 文本挖掘 防灾减灾;台风案例、干旱案例、暴雨案例
历史灾害文献分析方法论的研究,是连接过去与未来的关键桥梁。通过对古籍、方志、档案等非结构化文本的系统性挖掘与量化分析,不仅能够重建千年尺度的灾害事件序列(如台风、洪旱等),弥补仪器观测数据的时空局限性&#…...
【java 13天进阶Day12】XML和Dom4j,装饰模式,工厂模式,commons-io工具包,Base64
XML XML 指可扩展标记语言(EXtensible Markup Language),由各种标记(元素标签)组成。 可扩展:所有的标签都是自定义的,可以随意扩展的,如 。 XML 是一种标记语言,很类似 HTML,HTML…...
vue3 Element-plus修改内置样式复现代码
笔者在修改Element-plus的内置样式时,遇到一点挫折,现提供需求场景与解决方案。 一、实现(1)透明弹窗可拖拽,且不影响点击弹窗外内容;(2)弹窗内置表格,表格需修改样式颜色…...
工作督导 | 具有边缘型人格障碍倾向的高危来访者,咨询师如何应对?
一个学校心理中心,可能同时有几十位乃至数百位同学在接受咨询,其中大约10-20%是重点难点个案,一次督导如果只能督导1-2个个案,不足以保障所有危重难个案的有如何处理恰当、方向正确、快速解决、高效工作,是学校心理咨询…...
一本通 2063:【例1.4】牛吃牧草 1005:地球人口承载力估计
Topic: Ideas: 为什么把这两道题放在一起呢?就是因为这两道题很类似,都是很简单的数学题,只要你会列出数学等式,你就学会这道题了! 下面把计算过程展示给大家 Code: //2025/04/18…...
图+文+语音一体化:多模态合成数据集构建的实战与方法论
目录 图文语音一体化:多模态合成数据集构建的实战与方法论 一、多模态合成数据的核心价值 二、系统架构概览 三、核心模块与实现建议 ✅ 1. 文→图:图像合成(Text-to-Image) ✅ 2. 图→文:自动描述(I…...
c++:c++中的输入输出(二)
1.getline getline是包含于头文件:<string>的函数 作用:读取一行字符串(包含空格) 使用格式:getline(cin,str); string a;getline(cin, a); 假设我们有一个场景是需要识别一行字符串中的字母a的个数,…...
UniApp + Cursor + Devbox 全栏平台开发教程:从0到完整项目打造
本文基于B站热门教程《一口气学会小程序 / App / H5开发:UniApp教程 + Cursor + Devbox》,https://www.bilibili.com/video/BV1W7QZYMEus/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=a1428945043b2df41c1896acb90d942a,进行全面扩展…...
电流模式控制学习
电流模式控制 电流模式控制(CMC)是开关电源中广泛使用的一种控制策略,其核心思想是通过内环电流反馈和外环电压反馈共同调节占空比。相比电压模式控制,CMC具有更快的动态响应和更好的稳定性,但也存在一些固有缺点。 …...
服务器架构:SMP、NUMA、MPP及Docker优化指南
文章目录 引言 一、服务器架构基础1. SMP(对称多处理,Symmetric Multiprocessing)2. NUMA(非统一内存访问,Non-Uniform Memory Access)3. MPP(大规模并行处理,Massively Parallel Pr…...
人脸识别联合行为检测的办公管理新模式
基于人脸识别与行为检测的办公智能化解决方案 一、背景 在传统办公场景中,员工考勤管理、工位使用情况统计、安全监控等环节存在诸多痛点。例如,传统考勤方式如指纹打卡、刷卡等存在代打卡现象,考勤数据不准确;对于员工是否在工…...
Python 写生成 应用商店(2025版) 网页 方便收集应用 ,局域网使用
工具【1】:nginx 配置 nginx.conf 文件 server { listen 8080; server_name example.com; location / { root E:/BIT_Soft_2025; index index.html index.htm; } # 定义错误页面 error_page 404 /4…...
Spring 单元测试核心注解全解:@InjectMocks、@MockBean、@Mock、@Autowired 的区别与实战
在编写 Spring Boot 应用的单元测试过程中,@InjectMocks、@MockBean、@Mock 和 @Autowired 是最常用的几个注解,但它们经常被混淆或误用,导致测试失败或注入错误。 本文将从本质区别、使用场景、示例代码、对比表格等多个维度,全面解析这几者的使用方法与差异,助你写出结…...
2025年大一训练-DP1
2025年大一训练-DP1 Problem A: 动态规划算法,从上往下一层层找到到达对应位置的最大值,最底下一行maxl的最大值即为答案 #include<bits/stdc.h> using namespace std; int lst[101][101]; int maxl[101][101];int main() {int n,i,j;while(cin&g…...
