JDBC&连接池&DBUtils

一、预处理对象

1.SQL注入问题
SQL注入:用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义。
假设有登陆案例SQL语句如下:

SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;

此时,当用户输入正确的账号密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:**‘XXX’ OR ‘a’=‘a’**时,则真正执行的代码变为:

SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此时,上述查询语句是永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL的注入问题。
为此,我们使用PreparedStatement来解决对应的问题。

2.API详解:预处理对象
PreparedStatement:预编译对象,是Statement对象的子类。
特点:
性能高
会把sql语句先编译
能过滤掉用户输入的关键字。
PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符 替换。

String sql = "select * from user where username = ? and password = ?";

PreparedStatement使用,需要通过以下3步骤完成:

  1. PreparedStatement预处理对象代码:
#获得预处理对象,需要提供已经使用占位符处理后的SQL语句
PreparedStatement psmt = conn.prepareStatement(sql)

2.设置实际参数

void setXxx(int index,Xxx,xx)将指定参数设置指定类型的值
	参数1:index实际参数序列号,从1开始。
	参数2:xxx实际参数值,xxx表示具体的类型。
例如:
setString(2,"1234")把sql语句中第2个位置的占位符?替换为实际参数“1234”

3.执行SQL语句:

int executeUpdate();--执行insert update delete语句。
ResultSet executeQuery();--执行select语句。
boolean execute();--执行select返回true执行其他的语句返回false.

举例:
1.插入

@Test
public void demo01(){
	//添加:向分类表中添加数据
	Connection conn = null;
	PreparedStatement psmt = null;
	ResultSet rs = null;

	try{
			//1获取连接
			conn = JdbcUtils.getConnection();
			//2处理sql语句
			String sql = "insert into category(cname) values(?)";
			//3获得预处理对象
			psmt = conn.preparedStatement(sql);
			//4设置实际参数
			psmt.setString(1,"预处理");
			//5执行
			int r = psmt.executeUpdate();

			System.out.println(r);
		} catch (Exception e){
			throw new RuntimeException(e);
		}finally{
			//6释放资源
			JdbcUtils.closeResource(conn,psmt,rs);
	}
}

2.更新

@Test
public void demo02(){
	//修改
	Connection conn = null;
	PreparedStatement psmt = null;
	ResultSet rs = null;

	try{
		conn = JdbcUtils.getConnection();
		String sql = "update category set cname = ? where cid = ?";
		psmt = conn.preparedStatement(sql);
		psmt.setString(1,"测试数据");
		psmt.setInt(2,4);
		int r = psmt.executeUpdate();
		System.out.println(r);
	}catch(Exception e){
		throw new RuntimeException(e);
	}finally{
		JdbcUtils.closeResource(conn,psmt,rs);
	}
}

3.通过id查询详情

@Test
public void demo05(){
	//通过id查询
	Connection conn = null;
	PreparedStatement psmt = null;
	ResultSet rs = null;

	try{
	conn = JdbcUtils.getConnection();
	String sql = "select * from category where cid = ?"
	psmt = conn.preparedStatement(sql);
	psmt.setInt(1,2);
	rs = psmt.executeQuery();
	if(rs.next()){
		System.out.println("查询到");
	}else{
		System.out.println("查询不到");
	}
	
}catch(Exception e){
	throw new RuntimeException(e);
}finally{
	JdbcUtils.closeResource(conn,psmt,rs);
}
}

二、使用连接池重写工具类

1.连接池原理:

理解为存放多个连接的集合。
在这里插入图片描述
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能

2.编写标准的数据源(规范)

Java为数据库连接池提供了公共的接口:**javax.sql.DataSource,**各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3P0

3.C3P0连接池(这里只讲C3P0)

C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件 c3p0-config.xml
使用步骤:
1、添加jar包
2、编写配置文件:
c3p0-config.xml,放在src中(注:文件名一定不要写错

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/DB
		</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">root</property>
		<property name="initialPoolSize">3</property>
		<property name="maxPoolSize">6</property>
		<property name="maxIdleTime">1000</property>
	</default-config>
</c3p0-config>

3.编写工具类:

public class C3P0Utils{
	//创建一个连接池对象
	static DataSource ds = new ComboPooledDataSource();
	//从池中获得一个连接
	public static Connection getConnection() throws SQLException{
		return ds.getConnection();
	}
	//释放资源
	public static void closeAll(ResultSet rs,Statement stmt,Connection conn){
		if(rs!=null){
			try{
				rs.close();
			}catch(SQLException e){
				throw new RuntimeException(e);
			}
			rs = null;
		}
		if(stmt!=null){
			try{
				stmt.close();
			}catch(SQLException e){
				throw new RuntimeException(e);
			}
			stmt= null;
		}
		if(conn!=null){
			try{
				conn.close();
			}catch(SQLException e){
				throw new RuntimeException(e);
			}
			conn= null;
		}
	}
}

三、使用DBUtils 执行增删改查的操作

1.案例分析

简化JDBC代码开发,本案例我们将采用apache commons组件一个成员:DBUtils。
DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接),SQL语句都没有少

2.案例相关知识

2.1JavaBean组件
JavaBean就是一个类,在开发中常用于封装数据。具有如下特性:

  1. 需要实现接口:java.io.Serializable ,通常偷懒省略了。
  2. 提供私有字段:private 类型 字段名;
  3. 提供getter/setter方法:
  4. 提供无参构造
public class Category {
	
	private String cid;
	private String cname;
	
	public String getCid() {
		return cid;
	}
	public void setCid(String cid) {
		this.cid = cid;
	}
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
    …toString….
}

3.DBUtils完成CRUD

3.1概述
DBUtils是java编程中的数据库操作实用工具,小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码
Dbutils三个核心功能介绍
 QueryRunner中提供对sql语句操作的API.
 ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
 DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法

3.2QueryRunner核心类
 QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection
 update(String sql, Object… params) ,执行更新数据 insert update delete
 query(String sql, ResultSetHandler rsh, Object… params) ,执行查询 select

3.3ResultSetHandler结果集处理类
在这里插入图片描述
红色为重点掌握,其他了解

3.4实现
开发步骤:
1、创建项目,并导入jar包
2、创建连接池
3、编写测试类

添加

@Test
public void testInsert() {
	try {
		
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 sql
		String sql = "insert into category(cid,cname) values(?,?)";
		//3 参数
		Object[] params = {"c006","家电"};
		//4执行
		queryRunner.update(sql, params);
		
	} catch (Exception e) {
		throw new RuntimeException(e);
	} 
}

更新

@Test
public void testUpdate() throws Exception{
	try {
		
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 sql
		String sql = "update category set cname=? where cid = ?";
		//3 参数
		Object[] params = {"家电","c006"};
		//4执行
		queryRunner.update(sql, params);
		
	} catch (Exception e) {
		throw new RuntimeException(e);
	} 
	
}

删除

@Test
public void testDelete() throws Exception{
	try {
		
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 sql
		String sql = "delete from category where cid = ?";
		//3 参数
		Object[] params = {"c006"};
		//4执行
		queryRunner.update(sql, params);
		
	} catch (Exception e) {
		throw new RuntimeException(e);
	} 
}

通过id查询

@Test
public void testFindById() throws Exception{
	
	try {
		
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 sql
		String sql = "select * from category where cid=?";
		//3 参数
		Object[] params = {"c003"};
		//4执行
		Category category = queryRunner.query(sql, new BeanHandler<Category>(Category.class), params);
		
		System.out.println(category);
	} catch (Exception e) {
		throw new RuntimeException(e);
	} 
}

查询所有

@Test
public void testFindAll() throws Exception{
	try{
		//1核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2sql
		String sql = "select * from category";
		//3参数
		Object[] params = {};
		//4执行
		List<Category> allCategory = queryRunner.query(sql,new BeanListHandler<Category>(Category.class),params);
		for(Category category : allCategory){
			System.out.println(category);
		}
	}catch(Exception e){
		throw new RuntimeException(e);
	}
}

总记录数

@Test
public void testCount() throws Exception{
	try{
		//1核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2sql
		String sql = "select count(*) from category";
		//3参数
		Object[] params = {};
		//4执行
		Long numLong = (Long)queryRunner.query(sql,new ScalarHandler(),params);
		int num = numLong.inValue();
		System.out.println(num);
	}catch(Exception e){
		throw new RuntimeException(e);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值