Spring 数据库编程

news2025/7/13 5:51:03

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&amp;
                  characterEncoding=utf-8&amp;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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public int deleteAccount(int id) {
        String sql = "delete from account where id=?";
        int result = jdbcTemplate.update(sql, id);
        return result;
    }

    @Override
    public 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;
    }

    @Override
    public 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&amp;
                  characterEncoding=utf-8&amp;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 {
    @Test
    public 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("创建成功");
    }
    @Test
    public 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("添加失败");
        }
    }
    @Test
    public 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("修改失败");
        }

    }

    @Test
    public 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("删除失败");
        }
    }

    @Test
    public 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数据类型。

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

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

相关文章

进阶篇|CAN FD 与性能优化

引言 1. CAN vs. CAN FD 对比 2. CAN FD 帧结构详解

CTF--各种绕过哟

一、原网页&#xff1a; 二、步骤&#xff1a; 1.源代码&#xff1a; <?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…

嵌入式ARM RISCV toolchain工具 梳理arm-none-eabi-gcc

嵌入式TOOLchain工具 梳理 简介 本文总结和梳理一下一些toolchain的规则和原理&#xff0c;方便后续跨平台的时候&#xff0c;给大家使用toolchain做一个参考。 解释如何理解arm-none-eabi-gcc等含义&#xff0c;以及如何一看就知道该用什么编译器。 当然如果有哪里写的不是…

复现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 中&#xff0c; string 类的深浅拷贝有着重要的区别。 浅拷贝 深拷贝 string 类中的其他构造函数及操作 resize 构造 构造&#xff08;赋值构造&#xff09; 构造&#xff08;拼接构造&#xf…

第八篇:系统分析师第三遍——3、4章

目录 一、目标二、计划三、完成情况四、意外之喜(最少2点)1.计划内的明确认知和思想的提升标志2.计划外的具体事情提升内容和标志 五、总结 一、目标 通过参加考试&#xff0c;训练学习能力&#xff0c;而非单纯以拿证为目的。 1.在复习过程中&#xff0c;训练快速阅读能力、掌…

Unity粒子特效打包后不显示

1.粒子发mesh&#xff0c;如果打包后不显示&#xff0c;尝试勾选r/w 2.如果还不行&#xff0c;mesh重做&#xff0c;目前发现ab包打出的&#xff0c;有的mesh会出问题&#xff0c;暂时原因不详。

楼梯上下检测数据集VOC+YOLO格式5462张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;5462 标注数量(xml文件个数)&#xff1a;5462 标注数量(txt文件个数)&#xff1a;5462 …

消防营区管控:从智能仓储、装备管理、应急物资调用等多维度出发

近期&#xff0c;一系列消防安全热点事件引发了社会各界的广泛关注。某老旧城区的一场火灾&#xff0c;由于消防通道被杂物堵塞&#xff0c;消防车辆无法及时靠近火源&#xff0c;加之周边消防设施老化&#xff0c;灭火物资储备不足&#xff0c;导致火势迅速蔓延&#xff0c;造…

解锁古籍中的气候密码,探索GPT/BERT在历史灾害研究中的前沿应用;气候史 文本挖掘 防灾减灾;台风案例、干旱案例、暴雨案例

历史灾害文献分析方法论的研究&#xff0c;是连接过去与未来的关键桥梁。通过对古籍、方志、档案等非结构化文本的系统性挖掘与量化分析&#xff0c;不仅能够重建千年尺度的灾害事件序列&#xff08;如台风、洪旱等&#xff09;&#xff0c;弥补仪器观测数据的时空局限性&#…

vue3 Element-plus修改内置样式复现代码

笔者在修改Element-plus的内置样式时&#xff0c;遇到一点挫折&#xff0c;现提供需求场景与解决方案。 一、实现&#xff08;1&#xff09;透明弹窗可拖拽&#xff0c;且不影响点击弹窗外内容&#xff1b;&#xff08;2&#xff09;弹窗内置表格&#xff0c;表格需修改样式颜色…

一本通 2063:【例1.4】牛吃牧草 1005:地球人口承载力估计

Topic&#xff1a; Ideas&#xff1a; 为什么把这两道题放在一起呢&#xff1f;就是因为这两道题很类似&#xff0c;都是很简单的数学题&#xff0c;只要你会列出数学等式&#xff0c;你就学会这道题了&#xff01; 下面把计算过程展示给大家 Code&#xff1a; //2025/04/18…

c++:c++中的输入输出(二)

1.getline getline是包含于头文件&#xff1a;<string>的函数 作用&#xff1a;读取一行字符串&#xff08;包含空格&#xff09; 使用格式&#xff1a;getline(cin,str); string a;getline(cin, a); 假设我们有一个场景是需要识别一行字符串中的字母a的个数&#xff0c;…

电流模式控制学习

电流模式控制 电流模式控制&#xff08;CMC&#xff09;是开关电源中广泛使用的一种控制策略&#xff0c;其核心思想是通过内环电流反馈和外环电压反馈共同调节占空比。相比电压模式控制&#xff0c;CMC具有更快的动态响应和更好的稳定性&#xff0c;但也存在一些固有缺点。 …

人脸识别联合行为检测的办公管理新模式

基于人脸识别与行为检测的办公智能化解决方案 一、背景 在传统办公场景中&#xff0c;员工考勤管理、工位使用情况统计、安全监控等环节存在诸多痛点。例如&#xff0c;传统考勤方式如指纹打卡、刷卡等存在代打卡现象&#xff0c;考勤数据不准确&#xff1b;对于员工是否在工…

Python 写生成 应用商店(2025版) 网页 方便收集应用 ,局域网使用

工具【1】&#xff1a;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…

2025年大一训练-DP1

2025年大一训练-DP1 Problem A: 动态规划算法&#xff0c;从上往下一层层找到到达对应位置的最大值&#xff0c;最底下一行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…

架构图--架构师的行军地图

架构图是架构师最重要的沟通和规划工具之一&#xff0c;它如同行军地图般指导着整个软件系统的构建与演进。本文系统性地探讨了软件架构图设计的全面方法论&#xff0c;提出横向与纵向双维度的设计框架。横向设计关注模块间的业务、数据与重要性关系&#xff0c;纵向设计则采用…

OpenHarmony-Risc-V上运行openBLAS中的benchmark

OpenHarmony-Risc-V上运行openBLAS中的benchmark 文章目录 OpenHarmony-Risc-V上运行openBLAS中的benchmark前言一、编译openBLAS1.源码下载2.工具链下载3.编译并安装openBLAS 二、编译open BLAS中的benchmark三、上设备运行总结 前言 参考https://zhuanlan.zhihu.com/p/18825…

HAL库通过FATFS和SDIO+DMA写入SD卡数据错误

HAL库F4版本 1.28.1 最近在使用HAL库配置SDIODMA并通过FATFS向SD卡写入数据&#xff0c;但是发现写入的数据经常有错误&#xff0c;不是少了一部分就是多了一部分&#xff0c;写入的数据为csv格式&#xff0c;通过循环向缓冲区写入"100100,12.345678\r\n"数据来观察问…