数据库之简单练习

本文深入探讨JDBC的基本操作,包括使用PreparedStatement防止SQL注入,提高数据库操作的安全性和效率。同时,介绍了数据库连接池的概念,重点讲解了c3p0和Druid连接池的配置与使用,以及它们如何优化数据库连接的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回顾

1 DCL

修改自己密码

  -- 格式
  set password for '用户名'@'主机名'=password('新密码');

 

2 JDBC

JDBC是一套关系型数据库的规范(接口),我们程序员只需要掌握接口的方法即可

驱动:实现类由数据库厂商提供(jar)

JDBC基本操作

面向对象编程

面向接口编程(JDBC)

面向切面编程(spring)

面向服务编程(项目一、项目二)

  // 获取连接
  Class.forName("com.mysql.jdbc.Driver");
  connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/db_day04","root","root");
  // 创建语句执行者
  statement = connection.createStatement();
  // 编写sql
  String sql = "select * from user;";
  // 执行sql并返回结果
  resultSet = statement.executeQuery(sql);
  // 处理结果
  While(resultSet.next()){// 指针下移,并判断是否有记录 true | false
      // key(列名) =value(当前行对应的值)
      resultSet.getXxx(int 第几列,String 列名称)
          getString(); 直接接收任意类型-----底层强转
      
  } 
  // 关闭资源
  resultSet.close();
  statement.close();
  connection.close();

JDBC工具类

我们把JDBC操作的代码公共部分进行抽取,简化代码,提高效率

JDBC事务操作

通过Connection获取

  // 手动提交事务 (把自动提交关闭---mysql数据库一条sql一个事务)
  public void setAutoCommit(boolean false);
  // catch
  public void rollback();
  // try
  public void commit();

 

JDBC连接池&动态代理

1 PreparedStatement【掌握】

1.1 回顾上次登录案例

不输入密码一样可以登录成功!!!!!

问题

  SELECT * FROM USER WHERE username = 'admin '#' and password = 'banzhanganlianbanzhuren'

我们将用户输入的实际参数和sql字符串进行了拼接,发送给数据库先编译后执行,改变了sql原有的意义,我们称为sql注入

 

1.2 解决方案

我们不能把用户输入的实际参数和sql字符串进行了拼接,就要使用PreparedStatement对象来优化,处理sql注入

 

1.3 API介绍

通过Connection获取

  String sql ="select * from user where username =? and password =? "
  ​
  public PreparedStatement prepareStatement(sql);

设置参数

  // 支持java所有类型
  public void setXxx(int 第几个问号,Object 实际参数);
      int
      double
      String
      Object //万能

执行方法

  // sql
  public boolean execute();
  // dml
  public int executeUpdate();
  // dql
  public ResultSet executeQuery();

1.4 解决登录案例

参考:com.itheima.a_logindemo.LoginDemoPlus

1.5 优点

  1. 防止sql注入,提高安全

  2. 减少sql编译次数,提高效率

  3. 参数与sql字符串分离,提高程序可读性

1.6 实现增删改查

步骤分析

// 获取连接

// 编写sql

// 创建预编译语句执行者

// 设置参数

// 执行sql并返回结果

// 处理结果

// 关闭资源

新增

  // 新增
  @Test
  public void test01() throws Exception {
      // 获取连接
      Connection connection = JDBCUtilsPlus.getConnection();
      // 编写sql
      String sql = "insert into user values(null,?,?);";
      // 创建预编译语句执行者
      PreparedStatement preparedStatement = connection.prepareStatement(sql);
      // 设置参数
      preparedStatement.setObject(1, "rose");
      preparedStatement.setObject(2, "123");
      // 执行sql并返回结果
      int i = preparedStatement.executeUpdate();
      // 处理结果
      System.out.println(i);
      // 关闭资源
      JDBCUtilsPlus.closeResource(preparedStatement, connection);
  ​
  }

 

修改

  // 修改
  @Test
  public void test02() throws Exception {
      // 获取连接
      Connection connection = JDBCUtilsPlus.getConnection();
      // 编写sql
      String sql = "update user set password=? where id = ?;";
      // 创建预编译语句执行者
      PreparedStatement preparedStatement = connection.prepareStatement(sql);
      // 设置参数
      preparedStatement.setString(1, "667788");
      preparedStatement.setInt(2, 5);
      // 执行sql并返回结果
      int i = preparedStatement.executeUpdate();
      // 处理结果
      System.out.println(i);
  ​
      // 设置参数
      preparedStatement.setString(1, "112233");
      preparedStatement.setInt(2, 2);
      // 执行sql并返回结果
      i = preparedStatement.executeUpdate();
      // 处理结果
      System.out.println(i);
      // 关闭资源
      JDBCUtilsPlus.closeResource(preparedStatement, connection);
  ​
  }

 

删除

  // 删除
  @Test
  public void test03() throws Exception {
      // 获取连接
      Connection connection = JDBCUtilsPlus.getConnection();
      // 编写sql
      String sql = "delete from user where id = ?";
      // 创建预编译语句执行者
      PreparedStatement preparedStatement = connection.prepareStatement(sql);
      // 设置参数
      preparedStatement.setInt(1, 5);
      // 执行sql并返回结果
      int i = preparedStatement.executeUpdate();
      // 处理结果
      System.out.println(i);
      // 关闭资源
      JDBCUtilsPlus.closeResource(preparedStatement, connection);
  ​
  }

 

查询

课下作业

2 连接池【掌握】

2.1 概述

我们这二天使用JDBC操作每次都要创建连接、关闭连接,它是消耗资源和时间的,我们再项目初始化时创建一个池子,存放连接,再次使用连接时从池中获得,使用完毕后归还到连接池,提高连接的复用性,减轻服务器压力

 

DataSource

它是java对数据库连接池提供的一套规范(接口),我们程序员只需要掌握接口的使用方法,实现类由连接池厂商提供

2.2 c3p0

c3p0是一个开源连接池,目前hibernate等框架默认推荐使用

a)硬编码【了解】

步骤分析

1 导入jar包

2 编写代码

// 创建连接池对象

// 设置参数

// 获取连接

// 归还连接

b)配置文件【掌握】

步骤分析

1 导入jar包

2 定义一个配置文件

要求:

文件名:c3p0-config.xml

位置:src根目录下

3 编写代码

// 创建连接池对象

// 获取连接

// 归还连接

  public static void main(String[] args) throws Exception {
      // 创建连接池对象
      // ComboPooledDataSource() 会去src目录下 加载 c3p0-config.xml文件中的 <default-config> 配置信息 [推荐生产]
      // ComboPooledDataSource dataSource = new ComboPooledDataSource();
      // ComboPooledDataSource("dev")  会去src目录下 加载 c3p0-config.xml文件中的 <named-config name ="dev">配置信息
      ComboPooledDataSource dataSource = new ComboPooledDataSource("dev");
      // 获取连接
      Connection connection = dataSource.getConnection();
      System.out.println(connection);
      // 归还连接
      connection.close();
  ​
  }

 

2.3 druid

Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

配置文件【掌握】

1 导入jar包

2 定义一个配置文件

推荐:

文件名:druid.properties

位置:src根目录下

3 编写代码

// 创建连接池对象

// 获取连接

// 归还连接

  public static void main(String[] args) throws Exception {
      // 加载io流
      InputStream is = DemoUse.class.getClassLoader().getResourceAsStream("druid.properties");
      // 创建一个配置文件对象
      Properties properties = new Properties();
      properties.load(is);
      // 创建连接池对象
      DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
      // 获取连接
      Connection connection = dataSource.getConnection();
      System.out.println(connection);
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
      connection.close();// 明确 close方法是归还到连接池,它是对JDBC底层close方法进行了拓展(增强)
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
  ​
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
      System.out.println(dataSource.getConnection());
  ​
  ​
      System.out.println(dataSource.getConnection());
      // 归还连接
  ​
  }

2.4 连接池工具类【重要】

连接池是一个重量级对象,创建和销毁是非常非常非常消耗时间和资源,一般情况下一个项目初始化一次连接池,我们提到工具类,简化代码,提高效率

步骤分析

// 提供获取连接池的方法

// 提供获取连接的方法【常用】

// 提供归还连接 JDBCUtilsPlus(connection.clse()是归还连接池,而不是销毁对象)

3 动态代理【理解--框架使用】

刚才我们学习完了常用的连接池(Druid),我们知晓了如果连接需要归还给连接池,那么直接调用close方法即可。 但是我们在学习jdbc时调用connection.close() 是关闭连接,而现在是将连接还回连接池。这个是怎么做到的呢 ? 其实是对Connection的close方法进行了增强。

3.1 方法增强【理解】

a)继承

针对于目标类创建一个子类对象,重写父类的方法

不推荐使用

  1. 需要咱们自己写子类【麻烦】

    1. java是单继承,会占用一个继承位

b)动态代理

代理模式

 

动态代理

在程序运行期间,由JVM虚拟机帮你创建代理类对象,我们可以对目标类方法进行增强

常用动态代理技术

JDK、 CGLIB、JAVA ASSIST

JDK动态代理(sun公司自身提供的):要求目标类必须是接口的实现,JVM虚拟机根据接口创建代理类对象

3.2 代理案例【了解】

需求分析

薇薇老师在出道前免费唱歌,出道后,有了经纪人,先收费后唱歌;

步骤分析

1 接口 singer

唱歌

吃饭

2 创建目标类 Weiwei

微微一笑很倾城

珍珠翡翠白玉汤

3 创建代理类对象---实现对目标方法(唱歌)增强

Proxy工具类

代码实现

  // [了解]
  @Test
  public void test01() throws Exception {
      // 薇薇老师还未出道  栈内存  方法执行完毕 对象销毁
      // 栈内存 (逃逸分析)  激发你们的潜质  如果在方法中 创建了一个对象 ,其他方法没用调用的话  此方法 在栈,方法执行完毕 对象就会立马销毁
      Weiwei weiwei = new Weiwei();
      // weiwei.sing();
      // System.out.println(weiwei.eat());
  ​
      // 薇薇老师出道了,对唱歌方法进行增强  Proxy jdk提供的工具类
      /*
           * 参数一:目标类的加载器
           * 参数二:目标类的实现接口数组(java是单继承,多实现)
           * 参数三:调用增强接口,实现对目标类方法增强的
           *
           * */
      Singer weiWeiProxy = (Singer) Proxy.newProxyInstance(weiwei.getClass().getClassLoader(), new Class[]{Singer.class}, new InvocationHandler() {
          // 具体增强的业务逻辑,都写在这里
  ​
          /*
               * 参数一:代理对象本身  类似于 this
               * 参数二: 当前具体执行的方法  反射
               * 参数三:调用方法传递的实际参数数组 可变参数的底层就是数组
               *
               * */
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  ​
              System.out.println("invoke执行了");
              // 获取当前方法名
              String name = method.getName();
              if ("sing".equals(name)) {
                  System.out.println("收费10000元。。。。");
              }
              // 调用目标对象方法  实例在堆内存
              Object invoke = method.invoke(weiwei, args);
              // 返回给调用者
              return invoke;
          }
      });
  ​
      // 调用代理类对象的方法
      // weiWeiProxy.sing();
      System.out.println(weiWeiProxy.eat());
  }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值