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.hqwc.cn/news/267266.html

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

相关文章

了解网络攻击影响链的每个环节

通常很难完全理解成功的网络攻击的影响。有些后果显然是可以量化的&#xff0c;例如支付的赎金的数额。但其他后果并不那么明显&#xff0c;从客户信任和潜在业务的丧失&#xff0c;到数年后可能作为另一次网络攻击的一部分而出现的数据被盗。 这些都是网络攻击影响链的所有要…

扩展学习|商务智能与社会计算

一、概念介绍 &#xff08;一&#xff09;商务智能 商务智能&#xff08;Business Intelligence&#xff0c;简称BI&#xff09;是一种基于数据分析的决策支持系统&#xff0c;旨在帮助企业或组织更好地理解和利用自身数据&#xff0c;发现其中的模式和趋势&#xff0c;并提供…

C语言猜数字升级版

题目概述 猜数字是一种益智游戏&#xff0c;既可以两个人一起玩&#xff0c;也可以与电脑一起玩。现在我们需要将这个游戏移到电脑上&#xff0c;让电脑与我们一起玩猜数字游戏. 需求分析 用户输入&#xff1a;确定用户输入的数据是否正确游戏过程&#xff1a;保证计算机能正…

两线制无源 4-20mA 回路供电隔离变送器

两线制无源 4-20mA 回路供电隔离变送器 一入一出两线制无源 4-20mA 回路供电隔离变送器 概述&#xff1a;JSD TAW-1001D-100L-F 系列隔离变送器是 4-20mA 两线制回路供电的电流隔离变送配电器,该隔离变送器采用电磁隔离技术,并通过输入端馈电方式,给输入端两线制仪器仪表设备供…

javascript和HTML手机端实现多条件筛选的实战记录(筛选层的展示与隐藏、AJAX传输数组)

实现多条件筛选功能在JavaScript和HTML中可以分为以下几个步骤&#xff1a; HTML页面布局: 设计你的页面布局&#xff0c;包括筛选条件的选择器和结果展示区域。‘’ JavaScript逻辑:通过JavaScript监听筛选条件的变化&#xff0c;并根据选择的值对结果进行筛选。动态展示: 实…

nginx的location与rewrite

目录 一.location 二.rewrite rewrite跳转实现&#xff1a; 语法格式&#xff1a;rewrite [flag]; flag标记说明&#xff1a; 三.基于域名跳转 四.基于ip跳转 五.基于旧域名跳转到新域名后面加目录 六.基于参数匹配的跳转 可以同过全局变量来匹配&#xff1a; 基于目…

vue3 element-plus 日期选择器 el-date-picker 汉化

vue3 项目中&#xff0c;element-plus 的日期选择器 el-date-picker 默认是英文版的&#xff0c;如下&#xff1a; 页面引入&#xff1a; //引入汉化语言包 import locale from "element-plus/lib/locale/lang/zh-cn" import { ElDatePicker, ElButton, ElConfigP…

EasyExcel使用模板导出复杂Excel

1&#xff09;添加easyexlce的依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.0-beta1</version> </dependency>2&#xff09;添加excel模板文件 实现的效果&#xff1a;…

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

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

裸机单片机适用的软件架构

单片机通常分为三种工作模式&#xff0c;分别是 1、前后台顺序执行法 2、操作系统 3、时间片轮询法 1、前后台顺序执行法 利用单片机的中断进行前后台切换&#xff0c;然后进行任务顺序执行&#xff0c;但其实在…

【产品】Axure入门

Axure入门 一、Axure概述1.1 简介1.2 优点1.3 安装1.4 汉化 二、Axure的使用2.1 菜单栏2.1.1 菜单栏-文件2.1.2 菜单栏-视图 2.2 发布2.2.1 预览2.2.2 生成html代码 一、Axure概述 1.1 简介 Axure是一款专业的快速原型设计工具&#xff0c;全名为RP Axure。它是美国Axure Sof…

TypeScript 常用高级类型

目录 前言&#xff1a; TypeScript 常用高级类型 基本概念 高级类型 1. 交叉类型&#xff08;Intersection Types&#xff09; 2. 联合类型&#xff08;Union Types&#xff09; 3. 映射类型&#xff08;Mapped Types&#xff09; 4. 条件类型&#xff08;Conditional…