SSM学习——Spring JDBC

Spring JDBC

概念

Spring的JDBC模块负责数据库资源管理和错误处理,简化了开发人员对数据库的操作。

Spring JDBC通过配置数据源JDBC模板来配置。

针对数据库操作,Spring框架提供了JdbcTemplate类,它是Spring框架数据抽象层的基础,是Spring JDBC的核心类。

SpringTemplate

JdbcAccessor提供了访问数据库使用的公共属性,例如Data Source,DataSource主要功能是获取数据库连接,还可以引入对数据库连接的缓冲池和分布式事务的支持;JdbcOperations定义了可以使用的操作集合,例如增删改查(CURD)。

Spring JDBC模块由4个包组成:
Spring JDBC package

下面我们真正来用一下。

Spring JDBC实践

数据库创建

首先我们在MySQL中创建一个数据库,由于我是Mac环境,所以我直接在终端中执行SQL语句来完成。

如果你没有修改过密码,执行以下命令

mysql -uroot

如果修改过密码请执行以下命令,根据提示输入密码,输入的时候看不见

mysql -u root -p

如果你是Windows可以通过sqlyog连接。

以下部分通用:

执行SQL语句创建数据库

CREATE DATABASE db_javaee;

我们接下来为这个数据库创建一个单独的用户来管理它,用户名为db_javaee,密码是dbjavaeepassword

CREATE USER 'db_javaee'@'localhost' IDENTIFIED BY 'dbjavaeepassword';

这里有必要说明下,如果数据库与你开发环境在同一台机器上,这里可写'localhost',如果是远程的数据库要改为'%',即(以下同理)

CREATE USER 'db_javaee'@'%' IDENTIFIED BY 'dbjavaeepassword';

给这个用户授予权限,如果是远程别忘了改成'%'

GRANT ALL ON db_javaee.* TO 'db_javaee'@'localhost';

刷新权限

flush privileges;

这里有个问题得注意下,如果你的MySQL版本是5.7到这里就没啥问题了。如果是MySQL8.0以及更高,则加密算法由原来的sha256_password改成了caching_sha2_password,导致连接新版本数据库报错。

新版本用户需要追加

ALERT USER 'db_javaee'@'localhost' IDENTIFIED WITH mysql_native_password by 'dbjavaeepassword';

如果你root用户登陆不上也有可能是因为这个原因,这时候你就要像Mac用户一样到终端里连接,并将此处的db_javaee改为root才能在旧版sqlyog里或者navcat里连接。

项目创建

我们还是创建一个Maven项目,名称为top.cairbin.test3,然后在pom.xml里添加依赖包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.5.RELEASE</version>
    <scope>test</scope>
</dependency>

注意这里的mysql-connector-java请用较新的,我之前用5.1.47会报错。

同样创建与src平级的resources目录并use as source folder,在里面创建app.xml(跟我们之前的AppCtx.xml一样,名称不固定随你便,不过在main中的必须与这里的文件名一致),并写入如下内容

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 指定需要扫描的包,使注解生效 -->
	<context:component-scan
		base-package="top.cairbin.test3" />
	<!-- 配置dataSource -->
	<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/db_javaee" />
		<!--连接数据库的用户名 -->
		<property name="username" value="db_javaee" />
		<!--连接数据库的密码 -->
		<property name="password" value="dbjavaeepassword" />
	</bean>
	<!-- 配置JDBC模板 -->
	<bean id="jdbcTemplate"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<!-- 默认必须使用数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
</beans>

如果你数据库用户名和密码设置与我不一样,记得修改这里的value属性。

App.java中测试

package top.cairbin.test3;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;


public class App 
{
    public static void main( String[] args )
    {
    	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
    			// 获取JdbcTemplate实例
    			JdbcTemplate jdTemplate = 
    				   (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
    			// 使用execute()方法执行SQL语句,创建用户账户管理表account
    			jdTemplate.execute("create table account(" + 
    						         "id int primary key auto_increment," +
    						         "username varchar(50)," + 
    						         "balance double)");
    			System.out.println("账户表account创建成功!");

    }
}

点击运行按钮后就可以看到表创建成功了

编写测试

我们创建一个Account测试类

package top.cairbin.test3;

public class Account {
	private int id;       // 账户id
	private String username; // 用户名
	private double balance;  // 账户余额
	public Integer getId() {
		return id;
	}
	public void setId(Integer 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;
	}
	public String toString() {
		return "Account [id=" + id + ", "
				+ "username=" + username + 
				", balance=" + balance + "]";
	}
}

再建立一个IAccountDao接口

package top.cairbin.test3;

import java.util.List;

public interface IAccountDao {
	// 添加
	public int addAccount(Account account);
	// 更新
	public int updateAccount(Account account);
	// 删除
	public int deleteAccount(int id);	
	// 通过id查询
	public Account findAccountById(int id);
	// 查询所有账户
	public List<Account> findAllAccount();
}

然后定义AccountDao类实现这个接口

package top.cairbin.test3;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

@Repository("accountDao")
public class AccountDao implements IAccountDao {
	// 声明JdbcTemplate属性并添加注解
	@Autowired
private JdbcTemplate jdbcTemplate;
    // 添加账户
	public int addAccount(Account account) {
		// 定义SQL
		String sql = "insert into account(username,balance) value(?,?)";
		// 定义数组来存放SQL语句中的参数
		Object[] obj = new Object[] { 
                           account.getUsername(), 
                           account.getBalance() 
         };
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, obj);
		return num;
	}
	// 更新账户
	public int updateAccount(Account account) {
		// 定义SQL
		String sql = "update account set username=?,balance=? where id = ?";
		// 定义数组来存放SQL语句中的参数
		Object[] params = new Object[] { 
                               account.getUsername(), 
                               account.getBalance(), 
                               account.getId() 
          };
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, params);
		return num;
	}
	// 删除账户
	public int deleteAccount(int id) {
		// 定义SQL
		String sql = "delete from account where id = ? ";
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, id);
		return num;
	}
	
	// 通过id查询账户数据信息
	public Account findAccountById(int id) {
	    //定义SQL语句
	    String sql = "select * from account where id = ?";
	    // 创建一个新的BeanPropertyRowMapper对象
	    RowMapper<Account> rowMapper = 
	new BeanPropertyRowMapper<Account>(Account.class);
	    // 将id绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录
	    return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
	}
	// 查询所有账户信息
	public List<Account> findAllAccount() {
	    // 定义SQL语句
	    String sql = "select * from account";
	    // 创建一个新的BeanPropertyRowMapper对象
	    RowMapper<Account> rowMapper = 
	new BeanPropertyRowMapper<Account>(Account.class);
	    // 执行静态的SQL查询,并通过RowMapper返回结果
	    return this.jdbcTemplate.query(sql, rowMapper);
	}

}

创建测试类SpringJdbcTest,编写测试单元

package top.cairbin.test3;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class SpringJdbcTest {
	@Test
	public void mainTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("app.xml");
	    // 获取JdbcTemplate实例
	    JdbcTemplate jdTemplate = 
	            (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
	    // 使用execute()方法执行SQL语句,创建用户账户管理表account
	    jdTemplate.execute("create table account(" + 
	                           "id int primary key auto_increment," +
	                           "username varchar(50)," + 
	                           "balance double)");
	    System.out.println("账户表account创建成功!");
	}

	@Test
	public void addAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("app.xml");
	    // 获取AccountDao实例
	    IAccountDao accountDao = 
	            (IAccountDao) applicationContext.getBean("accountDao");
	    // 创建Account对象,并向Account对象中添加数据
	    Account account = new Account();
	    account.setUsername("tom");
	    account.setBalance(1000.00);
	    // 执行addAccount()方法,并获取返回结果
	    int num = accountDao.addAccount(account);
	    if (num > 0) {
	        System.out.println("成功插入了" + num + "条数据!");
	    } else {
	        System.out.println("插入操作执行失败!");
	    }
	}
	
	@Test
	public void updateAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    IAccountDao accountDao = 
	            (IAccountDao) applicationContext.getBean("accountDao");
	    // 创建Account对象,并向Account对象中添加数据
	    Account account = new Account();
	    account.setId(1);
	    account.setUsername("tom");
	    account.setBalance(2000.00);
	    // 执行updateAccount()方法,并获取返回结果
	    int num = accountDao.updateAccount(account);
	    if (num > 0) {
	        System.out.println("成功修改了" + num + "条数据!");
	    } else {
	        System.out.println("修改操作执行失败!");
	    }
	}
	
	@Test
	public void deleteAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("app.xml");
	    // 获取AccountDao实例
	    IAccountDao accountDao = 
	            (IAccountDao) applicationContext.getBean("accountDao");
	    // 执行deleteAccount()方法,并获取返回结果
	    int num = accountDao.deleteAccount(1);
	    if (num > 0) {
	        System.out.println("成功删除了" + num + "条数据!");
	    } else {
	        System.out.println("删除操作执行失败!");
	    }
	}
}

Eclipsesrc/main/java使用@Test注解需要进行配置:右键项目-> properties -> Java Build Path -> Libraries -> Add Library -> JUint

添加完成后导入包import java.util.List;就能用了。

点击运行,我这里已经测试了多次了,结果可能跟你的不一样

从图中左侧可以看到两个方法成功了,两个方法失败了。失败的方法图标又个红色的叉号。

我们再创建一个JdbcTemplateTest类,测试下查询方法

package top.cairbin.test3;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class JdbcTemplateTest {
	@Test
	public void findAccountByIdTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("app.xml");
	    // 获取AccountDao实例
	    IAccountDao accountDao = 
	            (IAccountDao) applicationContext.getBean("accountDao");
	    // 执行findAccountById()方法
	    Account account = accountDao.findAccountById(1);
	    System.out.println(account);
	}

	@Test
	public void findAllAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("app.xml");
	    // 获取AccountDao实例
	    IAccountDao accountDao = 
	            (IAccountDao) applicationContext.getBean("accountDao");
	    // 执行findAllAccount()方法,获取Account对象的集合
	    List<Account> account = accountDao.findAllAccount();
	    // 循环输出集合中的对象
	    for (Account act : account) {
	        System.out.println(act);
	    }
	}
}

关于SpringTest

在Spring中使用Junit测试,每一个测试方法都会初始化Spring容器,导致容器被初始化多次,需要通过ctx.getBean()获取测试Bean。

SpringTest可以解决上面的问题,通过在类之上添加注解即可

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")

这里的Junit版本为4.12,需要修改pom.xml
此处不对该功能过多解释。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基因组de novo组装

分以下几个部分&#xff1a; CLR组装 HIFI组装 ONT组装 二、三代数据矫正 组装结果评估 一、CLR组装 下机数据&#xff1a; 主要用那个bam文件 软件&#xff1a;wtdbg2 第一步&#xff1a;bam转fasta文件 参考&#xff1a;https://www.jianshu.com/p/03c7eb11102d # 进行基…

kali 渗透工具 - mestaploit

永恒之蓝漏洞的小知识&#xff1a; 黑客通过改造 永恒之蓝 制作 wannacry 制作病毒入侵高校内网。 mestaploit 攻击永恒之蓝流程&#xff1a; 使用模块 msfconsole配置required 模块参数运行&#xff0c;开始监听主机 msfconsole 主要模块 - 选择使用模块 search ms17_01…

VSCode 插件 Template String Converter

1. 插件介绍 点击安装 Template String Converter 插件 Template String Converter 翻译后&#xff1a;模板字符串转换器。 插件作用&#xff1a;当 JavaScript 字符串中键入 ${ 时自动将引号转为反引号&#xff0c;当删除 ${ 时自动将反引号转为普通引号 功能示例&#xff…

【T5中的激活函数】GLU Variants Improve Transformer

【mT5中的激活函数】GLU Variants Improve Transformer 论文信息 阅读评价 Abstract Introduction Gated Linear Units (GLU) and Variants Experiments on Text-to-Text Transfer Transformer (T5) Conclusion 论文信息 名称内容论文标题GLU Variants Improve Transfo…

【保姆级介绍Oracle】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

DeepWalk论文翻译

DeepWalk论文翻译 DeepWalk: Online Learning of Social Representations DeepWalk&#xff1a;社会表征的在线学习 ABSTRACT 我们提出了 DeepWalk&#xff0c;一种学习网络中顶点潜在表示的新方法。这些潜在表示在连续向量空间中对社会关系进行编码&#xff0c;很容易被统…

蓝桥杯第十五届抱佛脚(九)动态规划

蓝桥杯第十五届抱佛脚&#xff08;九&#xff09;动态规划 基本概念 动态规划(Dynamic Programming, DP)是一种用于解决复杂问题的优化算法设计技术。它将原问题分解为若干相互重叠的子问题,通过记录子问题的解,避免重复计算,从而大大减少了计算量。 动态规划典型的应用场景…

Python | SLP | EOF | 去除季节趋势

EOF & PC 前言 在计算EOF&#xff08;经验正交函数&#xff09;之前去除季节循环是为了消除数据中的季节变化的影响&#xff0c;使得EOF能够更好地捕捉数据中的空间变化模式。如果不去除季节循环&#xff0c;季节性信号可能会在EOF中占据较大的比例&#xff0c;从而影响对其…

【Greenplum】GP库 too many clients already错误,重启失败问题解决方案

问题描述&#xff1a; 连接数满了后&#xff0c;导致 gp库无法连接了&#xff0c;通过登录服务器&#xff0c;使用gpadmin用户进行重启操作&#xff0c;也报too many clients already&#xff0c;无法重启。 采用 psql -d postgres -U gpadmin 连接库&#xff0c;也报too man…

C语言----数据在内存中的存储

文章目录 前言1.整数在内存中的存储2.大小端字节序和字节序判断2.1 什么是大小端&#xff1f;2.2 练习 3.浮点数在内存中的存储3.1.引子3.2.浮点数的存储3.2.2 浮点数取的过程 前言 下面给大家介绍一下数据在内存中的存储&#xff0c;这个是一个了解c语言内部的知识点&#xf…

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

Golang | Leetcode Golang题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; func isMatch(s string, p string) bool {m, n : len(s), len(p)matches : func(i, j int) bool {if i 0 {return false}if p[j-1] . {return true}return s[i-1] p[j-1]}f : make([][]bool, m 1)for i : 0; i < len(f); i {f[i] m…

python--IO流和字符流的写入写出

1.IO流&#xff1a;&#xff08;input output stream&#xff09; python的IO流只有一个函数&#xff1a;open函数 属性不用带括号&#xff1b;方法通通要带括号 输入输出流&#xff1a;狭义上来说&#xff0c;指的就是内存数据和磁盘这种可以永久 存储数据的设备 IO流 IO流…

[C#]OpenCvSharp使用HoughCircles霍夫圆检测算法找出圆位置并计数

【效果展示】 原图&#xff1a; 找出位置&#xff1a; 【测试环境】 vs2019,netframework4.7.2,opencvsharp4.8.0 【函数用法】 cv2提供了一种圆检测的方法&#xff1a;HoughCircles。该函数的返回结果与参数设置有很大的关系。 检测的图像时9枚钱币&#xff0c;分别使用了…

Codeforces Round 931 (Div. 2) ---- E. Weird LCM Operations ---- 题解

E. Weird LCM Operations&#xff1a; 题目大意&#xff1a; 思路解析&#xff1a; 这是一道构造题&#xff0c;那么观察这个构造有啥性质&#xff0c;观察到最多操作次数为 n/6 5&#xff0c;然后每次操作需要选择三个数&#xff0c;如果每次操作的三个数都不和之前的重复的…

算法-最值问题

#include<iostream> using namespace std; int main() {int a[7];//上午上课时间int b[7];//下午上课时间int c[7];//一天总上课时间for (int i 0; i < 7; i) {cin >> a[i] >> b[i];c[i] a[i] b[i];}int max c[0];//max记录最长时间int index -1;//索…

解决 VSCode 编辑器点击【在集成终端中打开】出现新的弹框

1、问题描述 在 VSCode 的项目下&#xff0c;鼠标右键&#xff0c;点击【在集成终端中打开】&#xff0c;出现新的一个弹框。新版的 VSCode 会有这个问题&#xff0c;一般来说我们都希望终端是在 VSCode 的控制台中打开的&#xff0c;那么如何关闭这个弹框呢&#xff1f; 2、解…

震惊!!原来阻塞队列消息队列这样理解会更简单!!!

震惊!!原来阻塞队列&&消息队列这样理解会更简单!!! 一:阻塞队列二:消息队列2.1:生产者消费者模型2.1.1:解耦合:2.1.2:削峰填谷: 三:消息队列代码3.1.13.1.2:3.1.3:生产慢,消费快,消费阻塞3.1.3:生产快,消费慢,生产阻塞 二级目录二级目录 一:阻塞队列 阻塞队列:先进先出…

能耗监测管理系统与技术方案

能耗监测管理系统是目前能源管理中重要的技术手段&#xff0c;它通过集成现代监测技术和信息技术&#xff0c;实现对能源消耗的实时监控、数据分析和决策支持&#xff0c;帮助企业或机构实现能源的高效管理和节能降耗。本篇文章将从能耗监测管理系统的组成、关键技术、应用领域…

数据库重点知识(个人整理笔记)

目录 1. 索引是什么&#xff1f; 1.1. 索引的基本原理 2. 索引有哪些优缺点&#xff1f; 3. MySQL有哪几种索引类型&#xff1f; 4. mysql聚簇和非聚簇索引的区别 5. 非聚簇索引一定会回表查询吗&#xff1f; 6. 讲一讲前缀索引&#xff1f; 7. 为什么索引结构默认使用B…