上课同步视频: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
- …
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 语言的反射机制。反射是在程序运行过程中拿到类的字节码文件,进而获得类中的属性,方法等.
- 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 extends User> clazz3 = user.getClass( );if (clazz.equals(clazz2) && clazz2.equals(clazz3)) {System.out.println("是同一个字节码文件" );} else {System.out.println("不是" );}}
API |
---|
![]() |
/*** 获得字节码中的属性并操作*/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 );}
API |
---|
![]() |
/*** 获得字节码中的方法*/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);}
API |
---|
![]() |
/*** 获得字节码中的构造方法*/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的前提是,一定是完全按照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;}
}