JAVA12_06学习总结(JDBC,工具类优化)

news2024/12/23 12:14:21

今日内容

1. PreparedStatement

PreparedStatement
    --预编译
    步骤
        1)注册驱动
        2)获取数据库连接对象
        3)准备sql语句
            --不需要拼接
            --需要的参数全部使用 ? 占位符
        4)通过数据库连接对象,获取预编译对象,同时将sql语句房费数据库,将参数和参数类型都存储在预编译中
            Connection中的方法 
                PreparedStatement prepareStatement(String sql)
        5)给参数赋值
            void setXX(int Index,XX实际值)
                index -- 代表第几个参数
                实际值 -- 就是参数的实际值
        6)执行预编译对象 --在这里不用将sql语句给进去,因为第4步已经将语句传过去了,只需要执行即可
            int executeUpdate()
            ResultSet executeQuery()
        7)释放资源
import utils.JdbcUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
//预编译
public class preparedStatementTest {
    public static void main(String[] args) throws SQLException {
        //注册驱动,获取数据库连接对象
        Connection connection = JdbcUtils.getConnection();//调用工具类方法即可!
        //准备sql语句--使用?占位符,不需要拼接,大大提升安全性
        String sql = "insert into student values (?,?,?,?,?) ;" ;
        //获取执行对象--将sql语句传到数据库进行预编译--已经给数据库传过去了
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //给参数赋值
        preparedStatement.setInt(1,5); //一号参数id,赋值为5
        preparedStatement.setString(2,"胡桃"); //二号参数name,赋值胡桃
        preparedStatement.setInt(3,18); //三号参数age,赋值18
        preparedStatement.setString(4,"女"); //四号参数gender,赋值女
        preparedStatement.setString(5,"往生堂"); //五号参数address,赋值往生堂
        //执行语句
        preparedStatement.executeUpdate();//这里不给sql,sql已经传过去了
        //释放资源
        JdbcUtils.close(preparedStatement,connection);
    }
}

1.1 面试题

Statement和PreparedStatement的区别
    1)Statement
        --每次书写一条sql就需要通过Statment将sql语句发送给数据库
            -效率低并且数据库的压力大!
        --发送的sql语句存在字符串拼接
            -非常不安全--sql注入!--获取全部数据!
    2)PreparedStatement
        --将参数化的sql语句发送给数据库,进行预编译,以后执行语句只需要赋值即可,不需要重新传sql
            -效率高,数据库压力小
        --参数化的sql语句中,参数全部使用?占位符来代替,不存在拼接
            -安全

1.2 SQL注入

SQL注入安全问题
    在JDBC使用Statement获取执行对象,并将sql语句发送给数据库的过程中
        -用户利用sql拼接的漏洞,将用户名和密码全部绕过!
        举例
            select * from user where username='helloworld' and password = 'hello 'or '1'='1' ;
                --利用or的"或"特性--1是常量,恒成立--直接绕过用户名密码--直接访问其他人全部数据!
        解决方案
            全部使用PreparedStatement来进行后续过程!

2. JDBC方式控制事务

JDBC方式控制事务
    JDBC中如果不主动设置,默认自动提交!
        public void setAutoCommit(boolean autoCommit)
            --手动设置是否自动提交
                参数boolean autoCommit
                    -true,自动提交
                    -false,手动提交
        public void rollBack()
            --事务回滚,撤销之前的所有更新操作--前提是必须手动提交!
        public void commit()
            --手动提交
JDBC自动提交可能会出现的问题
    不控制事务 
        --执行多个sql语句期间出问题了,会造成数据紊乱!
import utils.JdbcUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
public class JDBCTransaction {
    public static void main(String[] args) throws SQLException {
        //利用表中数字增加减少举例
        //获取连接数据库
        Connection connection = JdbcUtils.getConnection();
        //准备sql语句
        //数字减少语句
        String sql1 = "update student set age = age - 100 where id = ? ; " ;
        //数字增加语句
        String sql2 = "update student set age = age + 100 where id = ? ; " ;
        //获取执行对象
        PreparedStatement ps1 = connection.prepareStatement(sql1);
        PreparedStatement ps2 = connection.prepareStatement(sql2);
        //参数赋值
        ps1.setInt(1,1);//给表中id为1的人减去100
        ps2.setInt(1,2);//给表中id为2的人加上100
        //执行
        ps1.executeUpdate();//执行减
        //制造错误
        int a = 1/0 ;//测试用错误
        ps2.executeUpdate();//执行加
        /*
            执行结果报错,但是数据库内容,该减的减了,该加的没加
         */
    }
}

 

解决方案
    手动开启提交,利用回滚解决安全问题
import utils.JdbcUtils;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
​
public class JDBCTransaction {
    public static void main(String[] args)  {
        //利用表中数字增加减少举例
        //获取连接数据库
        Connection connection = null ;
        PreparedStatement ps1 = null ;
        PreparedStatement ps2 = null ;
        try {
            connection = JdbcUtils.getConnection();
            //准备sql语句
            //数字减少语句
            String sql1 = "update student set age = age - 100 where id = ? ; " ;
            //数字增加语句
            String sql2 = "update student set age = age + 100 where id = ? ; " ;
            //获取执行对象
            ps1 = connection.prepareStatement(sql1);
            ps2 = connection.prepareStatement(sql2);
            //参数赋值
            ps1.setInt(1,1);//给表中id为1的人减去100
            ps2.setInt(1,2);//给表中id为2的人加上100
            //手动开启提交
            connection.setAutoCommit(false);//false为手动提交
            //执行
            ps1.executeUpdate();//执行减
            //制造错误
            int a = 1/0 ;//测试用错误
            ps2.executeUpdate();//执行加
            connection.commit();
        } catch (SQLException throwables) {
            try {
                //加入回滚,保证数据出错时一切回到未改变前!保证数据安全
                connection.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            throwables.printStackTrace();
        }finally {
            JdbcUtils.close(ps1,connection);
            JdbcUtils.close(ps2,connection);
        }
         /*
            执行结果报错 ,但是数据库没有任何改变,保护数据安全
         */
    }
}

 

3. 数据库连接池DateSource

数据库连接池DataSource
    DataSource可以看作数据源,它封装了数据库参数,连接数据库
        -程序中操作DataSource对象即可对数据库进行增删改查操作
    DataSource连接池--类比线程池
        连接池在创建的时候会带默认参数--从配置文件中获取
            默认创建一定数量的数据库连接对象
            每当使用完毕后会回到连接池中,等到下次继续使用!
Druid 德鲁伊!
    连接池工具--jar包
    来实现Java提供的DataSource接口
        参数
            driverClassName     创建驱动链接--com.mysql.jdbc.Driver
            url                 连接数据库链接--jdbc:mysql://localhost:3306/库名
            username            数据库用户名
            password            数据库密码
            initialSize         定义初始化连接数
            maxAction           最大连接数量
            maxWait             连接等待时间(毫秒值)--超过等待时间直接结束
    Druid获取连接数据库对象过程
        1)导包
        2)配置文件--严格按照Druid要求书写
        3)创建属性列表集合
            Properties
        4)读取配置文件
        5)将读取的字节输入流文件加载到属性列表中
        6)从连接池获取对象
            com.alibaba.druid.pool.DruidDataSourceFactory工厂类提供了方法
                --public static DataSource createDataSource(配置文件名)
                    --创建数据源DataSource数据源接口对象
                本质
                    DruidDataSource实现了DataSource接口
import com.alibaba.druid.pool.DruidDataSourceFactory;
​
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
​
//利用Druid连接池获取数据库连接对象
public class druidTest {
    public static void main(String[] args) throws Exception {
        //导包
        //书写配置文件
        //创建属性列表集合
        Properties prop = new Properties();
        //读取配置文件中的内容
        InputStream input = druidTest.class.getClassLoader()
                .getResourceAsStream("druid.properties");
        //将读取的内容加载到属性列表集合中
        prop.load(input);
        //利用DruidDataSourceFactory类方法实现DataSource接口
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //利用DataSource中方法getConnection()获取数据库连接对象
        Connection connection = dataSource.getConnection();
        //输出查看结果
        System.out.println(connection);
        /*
            十二月 06, 2022 8:44:24 下午 com.alibaba.druid.pool.DruidDataSource info
            信息: {dataSource-1} inited
            com.mysql.jdbc.JDBC4Connection@75412c2f
         */
        //释放资源,归还连接池
        connection.close();
    }
}

4. ThreadLocal

ThreadLocal--线程变量--与连接池连用,保护数据安全!
    隔离线程
        synchronized
            --使多个线程安全的抢占同一资源--数据共享
        ThreadLocal
            --使每个线程都使用自己的资源--数据隔离
    格式
        ThreadLocal<存储类型> 名 = new ThreadLocal<>()
    方法
        public T get()
            --获取当前线程中执行的值
        public void set(T value)
            --将任意内容绑定当前线程,不为空则更新,为空则直接赋值
        public void remove()
            --线程使用完毕之后,需要将内容从中解绑--否则可能会造成数据泄露

5. 优化Utils工具类-Druid-ThreadLocal

import com.alibaba.druid.pool.DruidDataSourceFactory;
​
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
​
//优化工具类,加入Druid和ThreadLocal
public class DruidUtils {
    //声明DataSource变量
    private static DataSource dataSource = null ;
    //声明ThreadLocal对象--存储连接对象,所以泛型存储Connection
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    //无参构造私有--外界不能创建实例
    private DruidUtils(){}
    //书写静态代码块,类加载就读取配置文件,完成数据库连接以及获取对象
    static {
        try {
        //创建属性集合列表
        Properties properties = new Properties();
        //读取配置文件
        InputStream inputStream = DruidUtils.class.getClassLoader()
                .getResourceAsStream("druid.properties");
        //将读取结果加载进列表
            properties.load(inputStream);
        //通过DruidDataSourceFactory类的方法获取DataSource对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //创建公共的获取数据源方法--后面有用
    public static DataSource getDataSource(){
        return dataSource ;
    }
    //创建公共的获取数据库链接对象的安全方法!--ThreadLocal
    public static Connection getConnection() {
        Connection connection = null ;
        //通过ThreadLocal获取一个线程
        connection = threadLocal.get() ;//因为存储的是Connection,所以取出也是
        //判断取出内容是否为空,是否占用已有内容线程
        if (connection==null){
            //当前线程没有连接对象,从连接池中取出一个绑定在一起
            try {
                connection = dataSource.getConnection();
                return connection ;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return null ;
    }
    //JDBC控制事务
    //手动开启事务
    public static void controlTransaction(){
        try {
            Connection connection = getConnection();
            connection.setAutoCommit(false);
​
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //回滚
    public static void rollBack(){
        Connection connection = getConnection() ;
        try {
            connection.rollback();
            connection.close(); //释放资源
            threadLocal.remove(); //解绑
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //提交
    public static void commit(){
        Connection connection = getConnection();
        try {
            connection.commit();
            connection.close();//释放资源
            threadLocal.remove();//解绑
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    //释放资源
    //释放资源--增删改
    public static void close(PreparedStatement preparedStatement, Connection connection){
        if (preparedStatement!=null){
            try {
                preparedStatement.close();//释放资源
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (connection!=null){
            try {
                connection.close();//释放资源
                threadLocal.remove(); //解绑
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    //释放资源--查询
    public static void close(ResultSet resultSet,PreparedStatement preparedStatement,Connection connection){
        if (resultSet!=null){
            try {
                resultSet.close();//释放资源
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (preparedStatement!=null){
            try {
                preparedStatement.close();//释放资源
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (connection!=null){
            try {
                connection.close();//释放资源
                threadLocal.remove(); //解绑
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

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

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

相关文章

均匀传输线的串扰和饱和长度

下图为串扰的电路模型&#xff0c;动态线与静态线之间通过互容与互感联系&#xff0c;这样也说明了动态线的信号耦合到静态线上的条件是存在di/dt或者dv/dt时&#xff0c;也就是说只在信号边沿上产生串扰&#xff0c;当电压或者电流为常数的时候静态线上就不会有串扰的信号。 信…

扩散模型:Diffusion models as plug-and-play priors作为即插即用先验的扩散模型

扩散模型&#xff1a;Diffusion models as plug-and-play priors作为即插即用先验的扩散模型0.摘要1.概述2.方法2.1.问题设置2.2.将去噪扩散概率模型作为先验3.实验&#xff1a;图像生成3.1.MNIST的简单说明3.2.使用现成组件条件生成脸部图像4.实验&#xff1a;语义分割附录B&a…

Ubuntu 20.04 系统最快安装WRF软件手册

前言 天气研究和预报&#xff08;WRF&#xff09;模型是一种中尺度数值天气预报系统&#xff0c;在全球范围内用于业务预报和研究目的。 这是在基于Intel的i7&#xff08;12核&#xff09;Linux Ubuntu 20.04 LTS系统上安装WRF 4.2.1的版本。这将有助于初学者在普通台式机上实现…

树莓派4b+mcp2515实现CAN总线通讯和系统编程(一.配置树莓派CAN总线接口)

文章目录前言硬件连线树莓派环境准备启用树莓派ssh启用mcp2515驱动下载can-utils工具测试CAN通讯开启CAN网卡测试发送和接收前言 树莓派本身是没有CAN通讯能力的&#xff0c;但他有mcp2515模块的驱动&#xff0c;可以通过SPI来控制mcp2515进行CAN的通讯。 本章主要讲,如何使能…

基于卡尔曼滤波的二维目标跟踪(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

双十二选哪个品牌led灯好一点?国产led灯这些品牌护眼好

现在绝大部分人造灯光都是使用led灯珠作为发光源了&#xff0c;所以led灯普遍的质量都比较好&#xff0c;也能护眼&#xff0c;特别是习惯晚上熬夜工作、学习、看书的人群&#xff0c;也都会选择led台灯来辅助照明&#xff0c;因为相比传统的家用室内顶灯&#xff0c;led护眼灯…

【小游戏】Unity游戏愤怒的足球(小鸟)

目录 1.弹弓逻辑 2.鸟的逻辑 3.GameManager主逻辑 文末有源工程地址 难度系数: ★★★★☆ 游戏玩法: 愤怒的足球,其实就是经典的愤怒的小鸟换图 项目简介: 功能完善,主要代码逻辑完整 本文内容: 记录一下这个工程,对内部代码逻辑没有深入了解有待以后发掘 1.弹弓逻…

workerman 聊天demo

1.demo下载 链接: https://pan.baidu.com/s/1MOqcDwvrZGgaYpZUBxxZiA 提取码: 2yqf 2.安装workerman 我这里使用的是tp5框架 下载官方压缩包解压到根目录 3.workerman 数据发送相关类 将worker目录放到项目extend文件夹中 4.启用workerman 登录服务器 linux启动方式&…

安卓APP源码和设计报告——购物APP的设计与实现

2021—2022学年第二学期期末考试 《Android手机软件开发》实践考核 项目设计说明书 项目名称&#xff1a; 购物APP的设计与实现 专 业&#xff1a; 计算机科学与技术 学 号&#xff1a; 姓 名&#xff1a; 任课教师&#xff1a; 2022年6月12日 目 录 1.项目概述11 2…

阿里云搭建博客之如何设置网页为中文

今天&#xff0c;在阿里云上参照“我的教程”–“搭建云上博客”中的指导&#xff0c;基于ApachemysqlWordPress搭建个人博客&#xff0c;参照上面的教程完成博客的搭建。但证登录博客后&#xff0c;发现业务展示为英文。在setting—>site language 设置中只有英文&#xff…

(附源码)springboot实验室预约管理系统 毕业设计 261141

实验室预约管理系统的设计与实现 摘 要 远程预约是一种全新的网络租用方式&#xff0c;它通过互联网突破了时间和空间限制&#xff0c;实现了便捷快速的预约与管理功能。在对数据信息有效组织并整合了一定使用功能后&#xff0c;远程预约系统可以方便地实现预约与取消&#xff…

如何在centos上安装nvidia驱动

首先查询服务器的gpu型号 [kfkbigdata-pro01 ~]$ lshw -C display WARNING: you should run this program as super-user. *-display description: VGA compatible controller product: SVGA II Adapter vendor: VMware physical id: f bus info: pci0000:00:0f.0 version: 00…

[附源码]JAVA毕业设计日常办公管理系统(系统+LW)

[附源码]JAVA毕业设计日常办公管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

【双碳环保】AcrelCloud-3500餐饮油烟监测云平台应用分析

背景概述 餐饮业油烟是大气中挥发性有机物&#xff08;VOCS&#xff09;和PM10的主要来源之一。近年来随着环保治理的加强&#xff0c;各地餐饮油烟条例相继推出&#xff0c;相关执法部门对大气监测&#xff0c;特别是餐饮油烟的治理监管都非常重视&#xff0c;为贯彻落实大气…

日本知名汽车零部件公司巡礼系列之株式会社123

株式会社123 业务内容&#xff1a; 各种自动组装机检测机的设计制作、半导体•液晶的设计制做、各种自动包装•省力化设备的设计制作、模具刀具的设计制作、各种零件的制作。 公司简介&#xff1a; 资本金&#xff1a;1000万日元&#xff08;2022年汇率折合人民币约50万元&a…

SystemV 信号量(一) —— SystemV信号量的相关操作函数

SystemV IPC 方案的相关内容都是通过 “房间密码”来创建房间&#xff0c;获取到房间的ID&#xff0c;后面其他进程也可以根据这个房间密码来拿到同一个房间的ID。这是理解下面这些操作函数的关键。 目录 1、信号量集合的创建 semget 2、信号量的初始化 / 销毁 semctl 3、信…

C/C++入门001-概述环境搭建与案例

文章目录1.C语言概述1.1 计算机与程序1.1.1 什么是计算机1.1.2 什么是计算机程序 ?1.2 进制转化1.3 计算机语言1.4 C语言发展1.5 安装开发工具与编译器1.5.1 安装 codeblocks1.5.2 设置MinGW的环境变量1.6 C语言的HelloWorld1.6.1 入门1.6.2 demo案例1.C语言概述 参考&#x…

基于jsp+mysql+ssm大学本科考研服务系统-计算机毕业设计

项目介绍 考研是一个艰难辛苦的过程&#xff0c;需要具备充沛的精力&#xff1b;考研是一场旷日持久的战争&#xff0c;需要吃苦耐劳的精神和持之以恒的毅力和意志&#xff0c;如果三天打鱼&#xff0c;两天晒网&#xff0c;那么很难在考研大军中胜出&#xff1b;考研的过程中…

UDP-阿拉伯糖,15839-78-8,UDP-L-Arabinose,阿拉伯糖偶联核苷酸

常用中文名&#xff1a;[[(2R,3S,4R,5R)-5-(2,4-dioxopyrimidin-1-yl)-3,4-dihydroxyoxolan-2-yl]methoxy-hydroxyphosphoryl] [(2R,3R,4S,5S)-3,4,5-trihydroxyoxan-2-yl] hydrogen phosphate 常用英文名&#xff1a;[[(2R,3S,4R,5R)-5-(2,4-dioxopyrimidin-1-yl)-3,4-dihydro…

windows个性化设置--自定义windows系统的u盘图标

选择一张图片&#xff0c;最好是正方形的&#xff0c;作为u盘图标 使用图片编辑软件将图片转换为ico格式 将x.icon图标放到u盘根目录 在u盘根目录下建立一个文本文件&#xff0c;编辑内容 [autorun] iconx.ico保存&#xff0c;将文本文件改名为autorun.inf 之后重新插拔u盘…