JDBC 使用PreparedStatement操作数据库 数据库 连接池 及 动态代理

JDBC 使用PreparedStatement操作数据库 数据库 连接池 及 动态代理

1 preparedStatement 预编译对象

2 数据库的连接池

3 动态代理

模拟用户登录功能

需求:
我们在控制台输入用户名和密码,输入完用户名和密码后,获取输入的值,使用jdbc操作数据库,完成登录功能.
找到了:登录成功 找不到:用户名或密码错误
技术分析:
jdbc

创建用户表:

    create table user (
      id int primary key auto_increment,
      name varchar(20),
      password varchar(20)
  );
  insert into user values(null,"tom","tom"),(null,"rose","rose"),(null,"jerry","jerry");、

代码实现:

public class LoginDemo {
    public static void main(String[] args) {
        Connection c = null;
        PreparedStatement pst = null;

        try {
            c = JDBCUtils.getConnection();
            //pst = c.prepareStatement();
            Scanner sc = new Scanner(System.in);
            System.out.println("----Welcome My Space----");
            System.out.println("Please input User name: ");
            String user = sc.nextLine();
            System.out.println("Please input User Password: ");
            String ps = sc.nextLine();
            //int psi = Integer.valueOf(ps);

            String sql = "select * from rentmoney where name=? and password=? ";
            pst = c.prepareStatement(sql);
            pst.setString(1,user);
            pst.setString(2,ps);

            ResultSet rs = pst.executeQuery();
            if(rs.next()){
                System.out.println("Yeah");
            }
            else{
                System.out.println("Fuck off");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeNew(null, pst, c);
        }
    }
}

Statement编译对象:拼接什么样的sql就执行什么样的sql语句

**问题:**使用Statement对象来操作sql语句会有缺陷:会造成数据的安全隐患

比如登录中的sql拼接:select * from user where username=‘jack’ #’ and password=‘123’;

相当于注释掉了密码的校验,这种安全隐患我们称为:Sql注入

Sql注入:将用户输入的内容作为了sql语句的一部分 改变了原有sql语句的意义

**解决:**就不能使用当前的Statement对象来操作SQL语句了,得使用另一个对象–preparedStatement对象

PreparedStatement: 预编译对象

**作用:**也是用来执行sql语句的

语句执行者:Statement编译对象 preparedStatement预编译对象

区别:

Statement编译对象是有什么样的sql就执行什么样的sql语句,每次执行任何一条sql语句都得先让数据库去编译 其后才执行 如果执行一万条同样的查询语句 数据库要编译一万次 效率低

preparedStatement预编译对象是先将sql传递给数据库做预编译 其后拿着预编译结果传递参数执行sql,执行一万条同样的查询语句 数据库只编译一次 根据不同的参数做不用的执行

预编译的好处:

1 sql语法格式只需要编译一次,效率高

2 能让数据库提前知晓要执行的sql语句格式,只负责给数据库传参即可

语法格式:

Statement编译对象: select * from 表 where 字段1=值1 and 字段2=值2;

preparedStatement:select * from 表 where 字段1=? and 字段2=?;

?:占位符 所有的实际参数都用占位符替换了 不在是直接设值了
通过外部方法来设置实际参数的值:set字段类型(占位符的序号,要设置的值);
占位符的序号是从1开始的
setString(1,‘jack’);
setString(2,‘abcd/1234’);

preparedStatement对象操作数据库的增删改查

使用步骤:

1.编写sql

  String sql = "insert into user values(null,?,?...) ";

2.创建预编译对象–提前编译sql语句

  PreparedStatement pst = conn.preparedStatement(sql);

3.设置具体的参数

  pst.set字段类型(int a,值);

  a: 第几个 ? (占位符)  默认从左向右第1个开始

4.执行sql即可

ResultSet rs = pst.executeQuery(); // 执行查询,返回 resultSet

int i = pst.executeUpdate(); // 执行 增 删 改 返回的是影响的行数

数据库连接池

概述

连接池:存放数据库连接的容器(集合)

连接池出现的目的

之前在使用jdbc操作数据库数据的时候,有一个步骤是获取连接(创建连接)
连接用完,还需要释放连接(销毁连接),这2个步骤太消耗资源了
创建连接=0.1
销毁连接=0.1
10000000*0.2=2000000
目标:想将获取连接和释放资源的这个时长缩短

用来优化jdbc的2个步骤的

1 优化的是jdbc的创建连接部分
2 优化的是jdbc的销毁连接部分

优化原理

在连接池一初始话的时候,就在容器中创建一定量的连接
当用户要连数据库的时候,就从容器中拿一个连接使用
使用完毕之后,不再是销毁,而是把使用后的连接还放回容器 供下一个用户去循环使用

ps:

在企业中使用的都是已经成熟并且性能很高的提供好的连接池:c3p0和druid(学习重点)

只要是直接研发连接池或者是别人研发连接池都需要先实现java提供的规则—DataSource接口

不论是哪个连接池都统一会有DataSource接口下的所有方法:

获取连接的方法(从连接池中获取): 连接池对象.getConnection() 
释放连接的方法(将连接归还给连接池): close() 
				只要当前要释放的连接是从连接池中拿的,当调用这个方法的时候是归还
				如果当前的要释放的连接不是从连接池中拿的,当调用这个方法的时候是销毁

c3p0连接池的使用

硬编码方式(必须要写代码实现的方式)
了解即可

配置文件方式(掌握)

硬编码方式开发步骤:
		 1 导包 c3p0-0.9.1.2.jar
		 2 创建连接池
		 3 告诉连接池要连接的数据库信息
		 4 (可选)连接池的参数配置
		 5 获取连接

配置文件方式(掌握)企业开发中我们配置文件会使用2种:.properties  key=value    .xml  层级关系
		 1 导包 c3p0-0.9.1.2.jar
		 2 在src下放一个配置文件
			     这个配置文件如果是xml的话,必须叫c3p0-config.xml 必须放在src下
			     这个配置文件如果是properties的话,必须叫c3p0.properties  必须放在src下
		 3 创建连接池获取连接
			 好处:只要连接池一创建 底层会自动去src下加载名字叫c3p0-config.xml或c3p0.properties文件
		 4 代码实现
	   		  1:创建c3p0的连接池:  DataSource ds=new CombopooledDataSource() 
	   									使用配置文件默认的<default-config>
	   					   DataSource ds=new CombopooledDataSource("name名称")													使用配置文件中带名称的<named-config name="otherc3p0"> 
	          2:从连接池中获取连接:	Connection con=ds.getConnection()
              3:拿着连接去操作数据库: 略
              4:归还连接给连接池:   con.close()	 

druid连接池的使用

配置文件方式(掌握)
	1 导入1个jar包 
		druid-1.0.9.jar
	2 存放配置文件
		 没有要求,可以是任何名称任何位置的properties文件即可(建议放入src下面)
		 原因:因为不会自动帮你去加载配置文件,需要自己手动去加载配置文件
	3 代码实现
	  1:创建properties对象加载配置文件
	  	     InputStream is=类名.class.getClassLoad.getResourceAsStream();
	  		 Properties properties= new Properties();
	  		 properties.load(is);		 
	  2: 创建druid的连接池
	  		  DataSource ds=DruidDataSourceFactory.createDataSource(properties对象)
	  3: 获取连接
      	      Connection con=ds.getConnection()
      4: 拿着连接去操作数据库: 略	   
      5:归还连接给连接池:   con.close()

自定义工具类(jdbcUtils)的增强

1 定义一个连接池(c3p0或druid)
2 提供获取连接的方法 (连接得是从连接池中拿的)
3 提供一个获取连接池的方法(直接返回连接池)—>jdbcTemplate工具类要用
4 提供释放资源的方法

动态代理
在这里插入图片描述
作用:用来增强一个对象的方法 (框架的底层用了很多的动态代理来增强方法业务)

代理的概念:
· 代理对象:增强对象
· 被代理对象:要被增强的对象

要使用jdk提供的动态代理增强一个对象的方法有条件:
· 必须得知道要被代理的对象是谁 被代理的对象必须得有接口

java:面向接口 先有接口后有类

使用jdk提供的动态代理:什么包都不用导 都提供好了

jdk提供工具API: newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 会返回一个指定接口下的代理类的代理对象

猜你喜欢

转载自blog.csdn.net/xc965746550/article/details/89367306