B029-JDBC增强

目录

      • PreparedStatement 查询
        • 1.sql注入
        • 2.Statement分析 (面试题)
        • 3.PreparedStatement (面试题)
      • 登录功能的完善
      • 事务
      • 链接池
        • 概念
        • 实现
          • DBCP连接池实现
            • 第一种配置方式
            • 第二种配置方式
      • 返回主键
      • BaseDao的抽取

PreparedStatement 查询

1.sql注入

就是在sql的字符串拼接的时候,加入了特定的条件判断,

如:SELECT * FROM student where name=’ 小坤坤255255 ’ OR 1=1

代码

public class StudentDaoImpl  implements IStudentDao{//Statement的写法@Overridepublic Student login(String name, String Password) {//通过工具类获取连接Connection conn = JDBCUtil.Instance().getconn();Statement State =null;ResultSet rs=null;Student student = new Student();try {State = conn.createStatement();rs = State.executeQuery("select * from student where name='"+name+"'and password ='"+Password+"'");while (rs.next()) {student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));} } catch (SQLException e) {e.printStackTrace();}finally {JDBCUtil.Instance().close(rs, State, conn);}return student;}
}
public class JDBCTest {@Testpublic void testName() throws Exception {StudentDaoImpl studentDaoImpl = new  StudentDaoImpl();//正常的代码
//		Student stu = studentDaoImpl.login("网通", "123");//sql注入的代码Student stu = studentDaoImpl.login("网通", "123' or '1=1");System.out.println(stu);if(stu.getName()!=null){System.out.println("账号存在登录成功");}else{System.out.println("账号不存在  ..登录失败");}}
}
2.Statement分析 (面试题)

1.通过上面sql注入的案例我们发现 Statement 它可能会导致sql注入的问题
2.通过这几天的sql的书写我发现 Statement 拼接sql相当复杂,稍微有一点点差错就会导致sql语句有问题

解决方法:PreparedStatement

3.PreparedStatement (面试题)

PreparedStatement 很好的解决了Statement的问题
1.不用担心注入问题(双引号之内看成一个整体的字符串而不是两个字符串和一个关键字),
2.sql语句不用复杂拼接,
3.会预处理sql语句,执行速度也更快

代码:
StudentDaoImpl

	//PreparedStatement写法@Overridepublic Student login(String name, String Password) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps=null;ResultSet rs =null;Student student = new Student();try {ps= conn.prepareStatement("select * from student  where name=? and password=?");ps.setString(1, name);ps.setString(2, Password);rs = ps.executeQuery();while(rs.next()){student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));}} catch (SQLException e) {e.printStackTrace();}finally {JDBCUtil2.Instance().close(rs, ps, conn);}return student;}

JDBCTest

	@Testpublic void testName() throws Exception {StudentDaoImpl studentDaoImpl = new  StudentDaoImpl();//正常的代码
//		Student stu = studentDaoImpl.login("网通", "123");//sql注入的代码Student stu = studentDaoImpl.login("网通", "123' or '1=1");System.out.println(stu);if(stu.getName()!=null){System.out.println("账号存在登录成功");}else{System.out.println("账号不存在  ..登录失败");}}

问题:PreparedStatement和Statement 不是同一个类为什么关资源的时候可以传PreparedStatement
因为 PreparedStatement 继承了 Statement,(多态)

PreparedStatement :

  // 预处理 这时候就会把sql发送到数据库了,只是这时还不会执行sqlselect * from student  where name=? and password=? 		//变量位置使用?先占住,(这时已经发了sql语句了)ps= conn.prepareStatement("select * from student  where name=? and password=?");// 把?替换成对应的值ps.setString(1, name);ps.setString(2, Password);// 执行sql  这时的执行就是一个执行命令,不会发sql语句(前面已发)rs = ps.executeQuery();

Statement:

  //创建 Statement 对象 State = conn.createStatement();// 发送并执行sql rs = State.executeQuery("select * from student where name='"+name+"'and password ='"+Password+"'");

PreparedStatement 是 Statement 子类,速度比Statement 快,能避免sql 注入,可以不用拼接sql语句

登录功能的完善

StudentDaoImpl

	@Overridepublic Student QueryByUsername(String name) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps = null;ResultSet rs = null;Student student = new Student();try {ps = conn.prepareStatement("select * from student where name=?");ps.setString(1, name);rs = ps.executeQuery();while (rs.next()) {student.setId(rs.getInt("id"));student.setName(rs.getString("name"));student.setPassword(rs.getString("password"));}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil2.Instance().close(rs, ps, conn);}return student;}

JDBCTest

	// 登录的第二种实现方式@Testpublic void login() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();// 查询是小坤坤(用户名)的信息,这个用户名 应该是前台(浏览器) 用户 传过来的 -- 模拟Student student = studentDaoImpl.QueryByUsername("小坤坤");// 判断用户名是否存在if (student.getName() == null) {System.out.println("账号不存在");}// else 就是账号存在else {// 判断这个账号的密码是否正确 (这个密码应该是前台(浏览器) 用户 传过来的)if (!"8848".equals(student.getPassword())) {System.err.println("密码错误");} else {System.out.println("登录成功");}}}

事务

	@Testpublic void Testtrans() throws Exception {Connection connection = null;PreparedStatement ps = null;PreparedStatement ps2 = null;try {connection = JDBCUtil2.Instance().getconn();// 不提交事务 (sql执行了,改变了数据库的数据,但是后面没有写提交事务数据库就不能有变化),connection.setAutoCommit(false);String sql = "update bank set money=money-1000 where name='过儿'";ps = connection.prepareStatement(sql);ps.execute();// 在这个位置 出现异常int a=0/0;String sql2 = "update bank set money=money+1000 where name='姑姑'";ps2 = connection.prepareStatement(sql2);ps2.execute();// 提交事物 (数据库可以发生变化了)connection.commit();} catch (Exception e) {// 回滚 (你数据库改变了之后我还是可以回滚)/*当我们把自动提交关闭,那sql就不是提交执行,于是我们一定要记住,当我们一个整体功能完成之后,自己要手动进行提交;--conn.commit但是失败之后,要记住数据回滚*/connection.rollback();} finally {ps2.close();ps.close();connection.close();}}

ACID (面试)
事务 : 一组操作 要么都成功 要么都失败
事务具有4个特征,分别是原子性、一致性、隔离性和持久性,简称事务的ACID特性;
原子性(atomicity) :一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作
一致性(consistency) : 一个事务执行前后,数据库都处于一致性状态
隔离性(isolation): 每一个事务都是单独的,事务和事务之间不影响
持久性(durability): 事务执行完了, 持久化到数据库

链接池

概念

在这里插入图片描述
你创建了一个池塘 池塘里面你放了很多链接 用完了就放回去 -->节省开关链接的时间

实现

在Java中,连接池使用javax.sql.DataSource接口来表示连接池,这里的DataSource就是连接池,连接池就是DataSource。
DataSource是接口,和JDBC一样,是Sun公司开发的一套接口,需要各大厂商实现;
需要导入相应包—导包…
所以使用连接池,首先需要导包;

常用的DataSource的实现有下面两种方式:
DBCP: Spring推荐的(Spring框架已经集成DBCP)
C3P0: Hibernate推荐的(早期)(Hibernate框架已经集成C3P0)持久层

DBCP连接池实现

1.导入jar包
commons-dbcp-1.3.jar,commons-pool-1.5.6.jar

2.代码
BasicDataSource就是DBCP的连接池实现

第一种配置方式
public class JDBCUtil {// 构造方法私有化private JDBCUtil() {};private static JDBCUtil instance;// 一启动就加载驱动 只执行一次static Properties ps = null;static BasicDataSource ds = null;static {ps = new Properties();try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));ds = new BasicDataSource();ds.setDriverClassName(ps.getProperty("dirverClassName"));ds.setUsername(ps.getProperty("username"));ds.setPassword(ps.getProperty("password"));ds.setUrl(ps.getProperty("url"));} catch (IOException e) {e.printStackTrace();}/*		 try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));Class.forName(ps.getProperty("dirverClassName"));} catch (Exception e) {e.printStackTrace();}*/instance = new JDBCUtil();}public static JDBCUtil Instance() {return instance;}// 写加载数据库的驱动public Connection getconn() {Connection connection = null;try {//换成新的获取连接池的方式connection = ds.getConnection();// connection = DriverManager.getConnection(ps.getProperty("url"),// ps.getProperty("username"), ps.getProperty("password"));} catch (Exception e) {e.printStackTrace();}return connection;}// 关闭资源public void close(ResultSet rs, Statement State, Connection conn) {try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (State != null) {State.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (conn != null) {conn.close();}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
}
public class test {public static void main(String[] args) {Connection connection = JDBCUtil.Instance().getconn();try {String sql = "update bank set money=money-500 where name='过儿'";PreparedStatement ps = connection.prepareStatement(sql);ps.execute();} catch (SQLException e) {e.printStackTrace();}}
}
第二种配置方式
public class JDBCUtil2 {// 构造方法私有化private JDBCUtil2() {};private static JDBCUtil2 instance;// 一启动就加载驱动 只执行一次static Properties ps = null;static DataSource ds = null;static {ps = new Properties();try {ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));// 创建连接池ds = BasicDataSourceFactory.createDataSource(ps);} catch (Exception e) {e.printStackTrace();}// try {// 		ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));// 		Class.forName(ps.getProperty("dirverClassName"));// } catch (Exception e) {// 		e.printStackTrace();// }instance = new JDBCUtil2();}public static JDBCUtil2 Instance() {return instance;}// 写加载数据库的驱动public Connection getconn() {Connection connection = null;try {//换成新的获取连接池的方式connection = ds.getConnection();// connection = DriverManager.getConnection(ps.getProperty("url"),// ps.getProperty("username"), ps.getProperty("password"));} catch (Exception e) {e.printStackTrace();}return connection;}// 关闭资源public void close(ResultSet rs, Statement State, Connection conn) {try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (State != null) {State.close();}} catch (SQLException e) {e.printStackTrace();} finally {try {if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}}}
}
public class test {public static void main(String[] args) {Connection connection = JDBCUtil2.Instance().getconn();try {String sql = "update bank set money=money-500 where name='过儿'";PreparedStatement ps = connection.prepareStatement(sql);ps.execute();} catch (SQLException e) {e.printStackTrace();}}
}

返回主键

场景举例:先后添加product和product_stock时,需要拿到product插入时自增的id存到product_stock的product_id里

看文档做

StudentDaoImpl

	@Overridepublic void insert(Student stu) {Connection conn = JDBCUtil.Instance().getconn();PreparedStatement ps = null;try {String sql = "insert into student(name,password) values(?,?)";ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);ps.setString(1, stu.getName());ps.setString(2, stu.getPassword());ps.executeUpdate();ResultSet rs = ps.getGeneratedKeys();while (rs.next()) {System.err.println(rs.getInt(1));}} catch (SQLException e) {e.printStackTrace();}}

JDBCTest

	@Testpublic void addStudent() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();Student stu = new Student();stu.setName("小波波");stu.setPassword("857857958958");studentDaoImpl.insert(stu);}

BaseDao的抽取

BaseDao

public class BaseDao {public void excuteUpdate(String sql, Object... objects) {Connection conn = JDBCUtil2.Instance().getconn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql);for (int i = 0; i < objects.length; i++) {ps.setObject(i + 1, objects[i]);}ps.execute();} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil2.Instance().close(null, ps, conn);}}
}

实现类:

public class StudentDaoImpl extends BaseDao  implements IStudentDao{@Overridepublic void insert(Student stu) {String  sql="insert into student(name,password) values(?,?)";excuteUpdate(sql, stu.getName(),stu.getPassword());}@Overridepublic void update(Student stu) {String sql = "update student set name=?,password=? where id =?";excuteUpdate(sql, stu.getName(),stu.getPassword(),stu.getId());}@Overridepublic void delete(Student stu) {String sql = "delete from student where id = ?";excuteUpdate(sql, stu.getId());}
}

JDBCTest

	@Testpublic void addStudent() throws Exception {StudentDaoImpl studentDaoImpl = new StudentDaoImpl();Student stu = new Student();stu.setName("小波波");stu.setPassword("857857");stu.setId(254172);
//		studentDaoImpl.insert(stu);
//		studentDaoImpl.delete(stu);studentDaoImpl.update(stu);}

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

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

相关文章

基于单片机的定时插座在智能家居中的应用

近年来&#xff0c;随着科学技术的发展迅速&#xff0c;人们对智能化的要求越来越高。越来越多的智能化产品进入千家万户&#xff0c;如电脑电视、扫地机器人、智能空气净化器等。这些家居电器和电子产品大都需要连接电源&#xff0c;为满足多种用电器的正常使用&#xff0c;延…

DevEco Studio 生成HPK文件

DevEco Studio 生成HPK文件 一、安装环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、生成HPK文件 生成的HPK文件存放在entry文件夹下。下图是未生成HPK的样式。 生成HPK&#xff1a;菜单Build->Build Hap(s)/APP(s)->Build Hap(s)…

启动jar包命令

一、Windows环境 找到jar包的位置&#xff1b; 按shift键&#xff0c;点击鼠标右键&#xff0c;选中在此处打开PowerShell窗口&#xff1b; 此时进入命令行工具 输入java -jar .\java_web-0.0.1-SNAPSHOT.jar&#xff08;注意空格&#xff09;。 二、Linux环境 2.1 方式一 …

039.Python面向对象_三大特性综合案例2

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

一、微前端目标、前端架构的前生今世、微前端架构优势和劣势、软件设计原则与分层

1、目标 2、前端架构的前世今生 ① 初始&#xff1a;无架构&#xff0c;前端代码内嵌到后端应用中 ② 后端 MVC 架构&#xff1a;将视图层、数据层、控制层做分离 缺点&#xff1a;重度依赖开发环境&#xff0c;代码混淆严重&#xff08;在调试时&#xff0c;需要启动后端所有…

小型洗衣机哪个牌子质量好?迷你洗衣机排名前十名

随着内衣洗衣机的流行&#xff0c;很多小伙伴在纠结该不该入手一款内衣洗衣机&#xff0c;专门来洗一些贴身衣物&#xff0c;答案是非常有必要的&#xff0c;因为我们现在市面上的大型洗衣机只能做清洁&#xff0c;无法对我们的贴身衣物进行一个高强度的清洁&#xff0c;而小小…

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 NLP 部分

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 NLP 部分 概述NLP 简介文本处理词嵌入上下文理解 文本数据加载to_device 函数构造数据加载样本数量 len获取样本 getitem 分词构造函数调用函数轮次嵌入 RobertaRoberta 创新点NSP (Next Sentence Prediction…

23种设计模式之装饰者模式(被装饰者,接口层,装饰抽象层,具体装饰者)

23种设计模式之装饰者模式 文章目录 23种设计模式之装饰者模式设计思想装饰者模式的优点装饰者模式的缺点装饰者模式的优化方法UML 解析预设场景 代码释义总结 设计思想 原文:装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0…

应用在LED灯光控制触摸屏中的触摸芯片

LED灯光控制触摸屏方法&#xff0c;包括&#xff1a;建立触摸屏的触摸轨迹信息与LED灯光驱动程序的映射关系&#xff1b;检测用户施加在触摸屏上的触摸轨迹&#xff0c;生成触摸轨迹信息&#xff1b;根据生成的触摸轨迹信息&#xff0c;调用对应的LED灯光驱动程序&#xff0c;控…

智能优化算法应用:基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于头脑风暴算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.头脑风暴算法4.实验参数设定5.算法结果6.…

智能优化算法应用:基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MA…

酷开科技多维度赋能营销,实力斩获三项大奖

在数智化新阶段、广告新生态、传播新业态的背景下&#xff0c;“第30届中国国际广告节广告主盛典暨网易传媒态度营销峰会”于11月18日在厦门国际会展中心盛大举行。来自全国的品牌方、战略决策者、媒体平台和品牌服务机构等汇聚一堂。在50000&#xff0b;现场观众和数千万线上观…

vue elementui点击按钮新增输入框(点多少次就新增多少个输入框,无限新增)

效果如图&#xff1a; 核心代码&#xff1a; <div v-for"(item,index) in arrayData" :key"item.id">//上面这个是关键代码&#xff0c;所有思路靠这个打通<el-inputtype"input" //除了输入框&#xff0c;还有textarea等placeholder&…

k8s详细教程(一)

—————————————————————————————————————————————— 博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码…

《Spring Cloud Alibaba 从入门到实战》分布式消息(事件)驱动

分布式消息&#xff08;事件&#xff09;驱动 1、简介 事件驱动架构(Event-driven 架构&#xff0c;简称 EDA)是软件设计领域内的一套程序设计模型。 这套模型的意义是所有的操作通过事件的发送/接收来完成。 传统软件设计 举个例子&#xff0c;比如一个订单的创建在传统软…

「差生文具多系列」推荐两个好看的 Redis 客户端

&#x1f4e2; 声明&#xff1a; &#x1f344; 大家好&#xff0c;我是风筝 &#x1f30d; 作者主页&#xff1a;【古时的风筝CSDN主页】。 ⚠️ 本文目的为个人学习记录及知识分享。如果有什么不正确、不严谨的地方请及时指正&#xff0c;不胜感激。 直达博主&#xff1a;「…

Fabric使用自己的链码进行测试-go语言

书接前文 Fabric链码部署-go语言 通过上面这篇文章&#xff0c;你可以部署好自己的链码 &#xff08;后面很多命令是否需要修改&#xff0c;都是根据上面这篇文章来的&#xff0c;如果零基础的话建议先看上面这篇&#xff09; 就进行下一步 在测试网络上运行自己的链码 目…

PDF文件的限制编辑,如何设置?

想要给PDF文件设置一个密码防止他人对文件进行编辑&#xff0c;那么我们可以对PDF文件设置限制编辑&#xff0c;设置方法很简单&#xff0c;我们在PDF编辑器中点击文件 – 属性 – 安全&#xff0c;在权限下拉框中选中【密码保护】 然后在密码保护界面中&#xff0c;我们勾选【…

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)

一、概述 上篇文章 系列九、SpringBoot MyBatis Redis实现分布式缓存 介绍了基于xml方式实现分布式缓存的效果&#xff0c;当前大家使用的技术栈基本是springboot各种框架的组合&#xff0c;而springboot显著的一个特点就是去xml配置&#xff0c;那么在无xml配置的情形下&…

界面控件DevExpress中文教程 - 如何用Office File API组件填充PDF表单

DevExpress Office File API是一个专为C#, VB.NET 和 ASP.NET等开发人员提供的非可视化.NET库。有了这个库&#xff0c;不用安装Microsoft Office&#xff0c;就可以完全自动处理Excel、Word等文档。开发人员使用一个非常易于操作的API就可以生成XLS, XLSx, DOC, DOCx, RTF, CS…