day38_JDBC
创始人
2025-06-01 10:45:14

今日内容

上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili
同步笔记沐沐霸的博客_CSDN博客-Java2301
零、 复习昨日
一、数据库连接池
二、反射
三、封装DBUtil

零、 复习昨日

SQL注入

预处理语句

String sql = "select * from user where id = ?";
PreparedStatement ps = conn.preparedStatement(sql);
ps.setInt(1,id);
// ps.setDate(1,new java.sql.Date(user.getDate().getTime()))
ps.executeQuery();

DBUtil

一、数据库连接池

目前数据库连接是使用是建立连接,用完直接关闭连接.即需要不断创建和销毁连接.就会消耗系统资源.借鉴线程池的思想,设计出数据库连接池.

在程序初始时,预先创建好指定数量的数据库连接对象,存储连接池。需要用时就去取,用完就放回去即可。就会不会频繁创建和销毁,从而节省系统资源。

使用上的线程池有很多

  • druid (德鲁伊)
  • c3p0
  • dbcp

1.1 Druid数据库连接池

Druid是阿里开源技术,性能很好

使用步骤

  • 导入依赖druid.jar包

  • 创建一个db.properties

    # 必须是driverClass,不是jdbc.driverClass,否则创建DataSource失败
    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/database?useSSL=false
    username=root
    password=123456
    # ----- 加入druid的一些连接配置
    #
    initialSize=10
    #最大连接数量
    maxActive=50
    #
    minIdle=5
    #
    maxWait=5000
    
  • 修改之前的DBUtil

    public class DBUtil {// 创建Properties类对象,专用于操作properties文件private static final Properties properties = new Properties();// 声明Druid连接池的连接池对象// 数据连接,一般称作数据源 dataSourceprivate static DruidDataSource dataSource;
    
  static {try {InputStream inputStream = DBUtil.class.getResourceAsStream("/db.properties");properties.load(inputStream);// 不需要由我们加载驱动// 需要给dataSource赋值dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {System.out.println("加载驱动异常!!" );e.printStackTrace( );}}public static Connection getConnection() {Connection conn = null;try{// 不需要我们获得连接// 而是通过Druid获得conn = dataSource.getConnection();} catch (Exception e) {System.out.println("获得连接出异常!!!" );e.printStackTrace();}return conn;}// 后续正常...跟之前一样

}

  • 开始使用

    • 跟之前一样使用

二、反射

JAVA反射(reflect)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对 象,都能够调用它的任意一个方法和属性

这种动态获取的信息以及动态调用对象的方法的功能称为java 语言的反射机制。

反射是在程序运行过程中拿到类的字节码文件,进而获得类中的属性,方法等.

2.1 获得类的字节码文件

  • Object类的方法 getClass()
  • 类的静态属性 Xxx.class
  • Class类的静态方法Class.forName(“xxx”)
   /*** 演示获取字节码文件*/public static void getClassFile() throws ClassNotFoundException {// 方式1Class clazz = Class.forName("com.qf.model.User");// 方式2Class clazz2 = User.class;// 方式3User user = new User( );Class clazz3 = user.getClass( );if (clazz.equals(clazz2) && clazz2.equals(clazz3)) {System.out.println("是同一个字节码文件" );} else {System.out.println("不是" );}}

2.2 获得并设置属性(Field)

API
image-20230322084435433
    /*** 获得字节码中的属性并操作*/public static void getAndSetFields() throws Exception {Class clazz = User.class;/*** Filed getField(String name)*       通过属性名获得属性对象(只能获得public修饰的属性的属性对象)* Filed getDeclaredField()*       通过属性名获得属性对象(获得任意修饰符修饰的属性对象)*/// Field id = clazz.getField("id");// System.out.println(id );Field id1 = clazz.getDeclaredField("id");System.out.println(id1 );/*** Filed[]  getFields( ) 获得public修饰所有属性对象,返回数组* Filed[] getDeclaredFields( )  获得所有属性对象,返回数组*/Field[] fields = clazz.getFields( );System.out.println(fields.length );Field[] declaredFields = clazz.getDeclaredFields( );System.out.println(declaredFields.length );// =============================================// 获得属性名String name = id1.getName( );System.out.println("name = "+ name );// 获得属性访问修饰符int modifiers = id1.getModifiers( );System.out.println("访问修饰符: " + modifiers );// 获得属性值// 获得哪个对象的该属性值// 但是不能获得私有属性的值// 可以通过设置,就可以访问,id1.setAccessible(true);User user = new User( );int value = id1.getInt(user);System.out.println("id = " + value );// 设置属性值// 设置哪个对象的该属性值id1.setInt( user,11);System.out.println(user );}

2.3 获得并设置方法(Method)

API
image-20230322084508059
    /***  获得字节码中的方法*/public static void getAndSeMethod() throws Exception {Class clazz = User.class;// 方法有重载,需要通过参数来确定获得哪个方法Method m1 = clazz.getMethod("m1"); // 获得无参的m1方法Method m1_ = clazz.getMethod("m1",int.class); // 获得有参的m1(int)方法// 获得关于方法的所有信息int count = m1.getParameterCount( );// 参数个数int count_ = m1_.getParameterCount( );// 参数个数// 操作方法,让方法执行// 参数1: 哪个对象的该方法执行// 参数2: 该方法执行时的参数Object ret = m1.invoke(new User( ));System.out.println("m1()执行后的返回值:" + ret );m1_.invoke(new User(),222);}

2.4 获得并设置构造方法(Constructor)

API
image-20230322084547730
    /***  获得字节码中的构造方法*/public static void getAndSeConstructor() throws Exception {Class clazz = User.class;// 通过参数来获得有参还是无参构造Constructor constructor = clazz.getConstructor( );// 构造方法执行,创建对象User user = constructor.newInstance( );System.out.println(user );// 创建字节码的对象,还有另外方法// 可以通过字节码,直接创建User user1 = clazz.newInstance( );}

三、使用反射封装DBUtil

能利用反射封装DBUtil的前提是,一定是完全按照ORM设计的类.

即 表名即类名,字段名即属性名

package com.qf.util;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;/*** --- 天道酬勤 ---** @author QiuShiju* @desc*/
public class DBUtil {// 创建Properties类对象,专用于操作properties文件private static final Properties properties = new Properties( );// 声明Druid连接池的连接池对象// 数据连接,一般称作数据源 dataSourceprivate static DruidDataSource dataSource;static {try {InputStream inputStream = DBUtil.class.getResourceAsStream("/jdbc.properties");properties.load(inputStream);// 不需要由我们加载驱动// 需要给dataSource赋值dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {System.out.println("加载驱动异常!!");e.printStackTrace( );}}public static Connection getConnection() {Connection conn = null;try {// 不需要我们获得连接// 而是通过Druid获得conn = dataSource.getConnection( );} catch (Exception e) {System.out.println("获得连接出异常!!!");e.printStackTrace( );}return conn;}/*** 关闭所有流*/public static void closeAll(Connection conn, Statement s) {if (conn != null) {try {conn.close( );} catch (SQLException throwables) {throwables.printStackTrace( );}}if (s != null) {try {s.close( );} catch (SQLException throwables) {throwables.printStackTrace( );}}}public static void closeAll(Connection conn, Statement s, ResultSet rs) {if (conn != null) {try {conn.close( );} catch (SQLException throwables) {throwables.printStackTrace( );}}if (s != null) {try {s.close( );} catch (SQLException throwables) {throwables.printStackTrace( );}}if (rs != null) {try {rs.close( );} catch (SQLException throwables) {throwables.printStackTrace( );}}}/*** 封装查询方法,返回一个对象* 参数1 执行查询的SQL,预处理的,条件用?占位* select * from tb_user where id = ? and username = ? and password = ?* 参数2 结果要封装的类* 参数3 给?赋值,不定长参数,是数组* 1,admin,123456*/public static  T selectOne(String sql, Class t, Object... args) {Connection conn = getConnection( );PreparedStatement ps = null;ResultSet rs = null;T target = null;try {ps = conn.prepareStatement(sql);for (int i = 0; args != null && i < args.length; i++) {ps.setObject(i + 1, args[i]);}rs = ps.executeQuery( );/*** 创建对象* 从数据库取出数据,并设置对象属性*/while (rs.next( )) {target = t.newInstance( );Field[] declaredFields = t.getDeclaredFields( );for (int i = 0; i < declaredFields.length; i++) {Field field = declaredFields[i];Object value = rs.getObject(field.getName( ));// 破解私有field.setAccessible(true);// 给对象的该字段赋值field.set(target, value);}}} catch (Exception e) {e.printStackTrace( );} finally {closeAll(conn, ps, rs);}return target;}public static  List selectAll(String sql, Class t, Object... args) {Connection conn = getConnection( );PreparedStatement ps = null;ResultSet rs = null;T target = null;ArrayList list = new ArrayList<>( );try {ps = conn.prepareStatement(sql);for (int i = 0; args != null && i < args.length; i++) {ps.setObject(i + 1, args[i]);}rs = ps.executeQuery( );/*** 创建对象* 从数据库取出数据,并设置对象属性*/while (rs.next( )) {target = t.newInstance( );Field[] declaredFields = t.getDeclaredFields( );for (int i = 0; i < declaredFields.length; i++) {Field field = declaredFields[i];Object value = rs.getObject(field.getName( ));// 破解私有field.setAccessible(true);// 给对象的该字段赋值field.set(target, value);}list.add(target);}} catch (Exception e) {e.printStackTrace( );} finally {closeAll(conn, ps, rs);}return list;}/*** 增删改方法一样*/public static boolean update(String sql, Object... args) {Connection conn = getConnection( );PreparedStatement ps = null;int num = 0;try {ps = conn.prepareStatement(sql);for (int i = 0; args != null && i < args.length; i++) {ps.setObject(i + 1, args[i]);}num = ps.executeUpdate( );} catch (Exception e) {e.printStackTrace( );} finally {closeAll(conn, ps);}return num > 0 ? true : false;}
}

相关内容

热门资讯

2025新版教程“皮皮斗地主到... 2025新版教程“皮皮斗地主到底是不是有挂”确实真的有挂(详细教程)是一款可以让一直输的玩家,快速成...
2025新版教程“新时代到底是... 您好,新时代这款游戏可以开挂的,确实是有挂的,通过微信【29290261】很多玩家在这款游戏中打牌都...
2025新版教程“天狐游戏到底... 无需打开直接搜索微信:天狐游戏有挂吗本司针对手游进行,选择我们的四大理由:1、软件助手是一款功能更加...
2025新版教程“鲨鱼麻将到底... 【无需打开直接搜索微信;29290261】 操作使用教程:1.亲,实际上鲨鱼麻将是可以开挂的,确实有...
2025新版教程“闲逸麻将到底... 自定义闲逸麻将系统规律,只需要输入自己想要的开挂功能,一键便可以生成出闲逸麻将专用辅助器,不管你是想...