DbUtils,BeanUtils,Druid 第三方工具使用

DbUtils,BeanUtils,Druid 第三方工具使用

1. DbUtils 工具类

1.2 ORM 思想
	对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的资料之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。	

数据库表设计: table Student
	id int 
	name varchar(32)
	age int

Java当中的 JavaBean 规范类设计
	class Student {
		Integer id;
		String name;
		Integer age;
	}

设计数据库尽量保证字段名称和类成员变量名称一致,后期要考虑前端提交数据信息(Key=Value)键值对模型,Key也要符合映射关系。

例如:
	前端提交数据:
		id=1&name=张三&age=15
	
	后台接收数据:
		id=1&name=张三&age=15 ==> 数据解析 ==> Student 对象
			1. split("&") ==> String[] {"id=1", "name=张三", "age=15"}
			2. 每一个元素 substring 
				"id=1" ==> substring
					第一部分数据: "id"    第二部分数据: "1"
			3. BeanUtils.setProperty(stu, "id", "1");
		
		是否可以采用Map类型传递存储???
		是否可以采用数组类型传递存储???
	
	数据库存储数据:
		Student[id=1, name=张三, age=15] ==> table student 
2.2 DbUtils 介绍
apache 组织轻量级 ORM 数据库框架

核心类:
QueryRunner 对应的构造方法
	QueryRunner();
		实例化 QueryRunner 对象,在后期执行 SQL 语句操作过程中,需要提供数据库连接对象完成 SQL 语句执行

	QueryRunner(java.sql.DataSource dataSource);
		实例化 QueryRunner 对象,给予 QueryRunner 构造方法数据库连接池对象,后期操作直接使用

核心方法:
	public int update(String sql, Object... parameterValues);
		通过 QueryRunner 对象调用执行 update delete insert 操作
	public int update(Connection connection, String sql, Object... parameterValues);
		通过 QueryRunner 对象调用执行 update delete insert 操作,需要提供当前操作对应的数据库连接对象
		
	public <T> T query(String sql, ResultSetHandler<T> rsh, Object... parameterValues)
		通过 QueryRunner 对象调用执行 select 操作,查询结果集的最终数据处理方式由 ResultSetHandler 接口
		实现类决定
	public <T> T query(Connection connection, String sql, ResultSetHandler<T> rsh, Object... parameterValues)
		通过 QueryRunner 对象调用执行 select 操作,查询结果集的最终数据处理方式由 ResultSetHandler 接口
		实现类决定,需要提供当前操作对应的数据库连接对象

interface ResultSetHandler<T>
	数据库查询结果集处理器
	要求实现的方法:
		T handler(ResultSet rs) throws SQLException
六个常用处理器:
	class BeanHandler<T>	单行数据 数据行内容映射 JavaBean 规范对象
	class BeanListHandler<T> 多行数据  数据行内容映射 JavaBean 规范对象 多行数据存储到 List 集合中

	class MapHandler 单行数据 数据行内容映射 Map<String, Object> 字段=>Key 数据=>Value
	class MapListHandler<T> 多行数据  数据行内容映射 Map<String, Object> 字段=>Key 数据=>Value
						多行数据存储到 List 集合中
						
	class ArrayHandler 单行数据 数据行内容映射 Object[] 仅存储数据
	class ArrayListHandler<T> 多行数据  数据行内容映射 Object[] 仅存储数据 多行数据存储到 List 集合中

2. BeanUtils JavaBean规范相关操作工具类

可以完成的任务有:
	1. 给予符合 JavaBean 规范类对象指定成员变量数据赋值操作
	2. 获取符合 JavaBean 规范类对象指定成员变量数据,数据返回形式为 String 字符串
	3. 可以完成从一个 JavaBean 规范类对象到另一个 JavaBean 类对象数据拷贝操作
	4. 可以将 Map 双边队列数据转换成一个 JavaBean 规范类对象

需要引入的第三方 Jar 包
	commons-beanutils-1.8.3.jar
	commons-logging-1.1.3.jar
	在 Java 开发中,使用的第三方 jar 包可能存在依赖问题
	想要使用 beanutils 工具类,必须提供 logging 对应 Jar 包

	后期依赖关系不需要程序员考虑,如果在使用第三方 Jar 包过程中,有对其他 jar 包依赖,可以使用 Maven 来管理项目,解决问题。
package com.qfedu.b_beanUtils;

import com.qfedu.a_jdbc.Student;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;

/**
 * BeanUtils 工具类演示
 *	1. 给予符合 JavaBean 规范类对象指定成员变量数据赋值操作
 * 	2. 获取符合 JavaBean 规范类对象指定成员变量数据,数据返回形式为 String 字符串
 * 	3. 可以完成从一个 JavaBean 规范类对象到另一个 JavaBean 类对象数据拷贝操作
 * 	4. 可以将 Map 双边队列数据转换成一个 JavaBean 规范类对象
 *
 * @author Anonymous 2022/4/7 14:41
 */
public class Demo1 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        // 1. 给予符合 JavaBean 规范类对象指定成员变量数据赋值操作
        Student stu1 = new Student();

        /*
        public static void setProperty(Object bean, String name, Object value);
        给予符合 JavaBean 规范类对象指定成员变量数据赋值操作,name 约束成员变量名称, value 是
        对应赋值使用的数据,类型不限制。
         */
        //BeanUtils.setProperty(stu1, "id", '1');
        //BeanUtils.setProperty(stu1, "id", "10");
        BeanUtils.setProperty(stu1, "id", 10);
        BeanUtils.setProperty(stu1, "name", "张三");
        BeanUtils.setProperty(stu1, "age", '9');
        BeanUtils.setProperty(stu1, "score", "100.50");
        /*
        成员变量 Boolean
            1 true ==> true
            其他数据 false ==> false
         */
        BeanUtils.setProperty(stu1, "married", 0);

        System.out.println(stu1);
        
        /*
        2. 获取符合 JavaBean 规范类对象指定成员变量数据,数据返回形式为 String 字符串
        public static String getProperty(Object bean, String name)
         */
        String id = BeanUtils.getProperty(stu1, "id");
        String name = BeanUtils.getProperty(stu1, "name");
        String age = BeanUtils.getProperty(stu1, "age");
        String score = BeanUtils.getProperty(stu1, "score");
        String married = BeanUtils.getProperty(stu1, "married");

        System.out.println(id);
        System.out.println(name);
        System.out.println(age);
        System.out.println(score);
        System.out.println(married);

        System.out.println();

        /*
        3. 可以完成从一个 JavaBean 规范类对象到另一个 JavaBean 类对象数据拷贝操作
         public static void copyProperties(Object dest, Object orig)
            dest 目标对象
            orig 数据源对象
         */
        Student student = new Student();
        System.out.println(student);
        BeanUtils.copyProperties(student, stu1);
        System.out.println(student);
    }
}

package com.qfedu.b_beanUtils;

import com.qfedu.a_jdbc.Student;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

/**
 * @author Anonymous 2022/4/7 15:09
 */
public class Demo2 {
    public static void main(String[] args)
            throws InvocationTargetException, IllegalAccessException {
        HashMap<String, Object> map = new HashMap<>();

        map.put("married", 1);
        map.put("age", "15");
        map.put("score", "100");
        map.put("id", 10);
        map.put("name", "张三");
//        map.put("salary", 100);

        Student stu = new Student();
        System.out.println(stu);
        /*
        public static void populate(Object bean, Map properties)
        将 Map 双边队列中的数据内容,map 中的 key 对应 符合 JavaBean 规范的成员变量名称
        使用对应 value 赋值成员变量数据,并且可以进行数据类型自动转换,如果key和成员变量
        不对应自动舍去数据。
         */
        BeanUtils.populate(stu, map);
        System.out.println(stu);
    }
}

3. 数据库连接池

3.1 数据库连接池可以解决什么问题
SQL操作流程
	1. 数据库连接对象获取
	2. query or update
	3. 数据库连接对象关闭

执行一条 SQL 语句,执行一次任务。需要创建/打开一次数据库连接对象,操作结束之后,销毁/关闭数据库连接对象。

周董开了一个餐厅:
	招服务员!!!
	服务员给顾客倒了一杯水。
	解雇了!!

这样会导致资源浪费!!!

周董开了一个餐厅:
	招聘了 5 个服务员
	服务员需要执行任务
	执行之后排到末尾等待下一次执行任务
3.2 数据库连接池配置文件必要内容分析
想要得到一个 java.sql.Connection 数据库连接对象,必须提供的信息有哪些???
	1. 驱动 driverClass
	2. jdbc规范数据库连接 url jdbcUrl
	3. 用户名和密码
	4. 初始化数据库连接池容量,创建数据库连接池对象,初始化有多少个 Connection 对象
	5. 可以设置最大容量 允许数据库连接池对象最大承载的 Connection 对象个数
	6. 数据库连接对象使用等待时间

数据库连接对象关闭调用哪一个方法???
	close(); 数据库连接对象资源关闭方法

	数据库连接池中的所有 java.sql.Connection 对象在执行任务之后,依然调用 close 方法对资源进行回收,但是 close 已被劫持。
	connection 执行 prepareStatement 方法 CPU 放行
	connection 执行 setXXXX 方法 CPU 放行
	connection 执行 getXXXX 方法 CPU 放行
	connection 执行 【close】 站住!!!【拦截】不再执行原本的 close 方法, 而是将当前对象归还到数据库连接
			池中,等待下一次执行任务使用。

数据库连接池算不算一个集合???
	LinkedList 增删快,查询慢
		队列,每一次获取数据库连接对象,都是从链表头获取,执行任务之后将数据库连接对象,放置到链表末尾
LinkedList<Connection> list = {
	c1, c2, c3, c4, c5
}

任务:
	c1 执行 ==》Connection list.removeFirst();
	
执行完毕:
	c1.close() ==> close 方法被【劫持】,不是真的关闭资源,而且存入到 LinkedList 末尾
	
	list.addLast(c1);

LinkedList<Connection> list = {
	c2, c3, c4, c5, c1
}
3.3 Druid 数据库连接池使用
需要提供第三方 Jar 包
	druid-1.2.3.jar
# druid.properties文件
# 文件名 druid.properties 存储在src目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaee_2203?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123456

# 初始化数据库连接池容量
initialSize=10

# 最大容量
maxActive=30

# TimeOut 等待超时时间
maxWait=2000
修改 JdbcUtils 工具类,引入 Druid 数据库连接池对象操作
package util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;

/**
 * 使用 Druid 数据库连接池优化数据库相关资源的管理。
 *
 * @author Anonymous 2022/4/1 16:11
 */
public class JdbcUtils {

    /**
     * 定义静态成员变量 javax.sql.DataSource 数据库连接池对象
     * 【数据源】
     */
    private static DataSource pool;

    /*
    利用静态代码块,在加载程序中的过程中,读取 druid.properties 文件,解析内容,用于数据库连接必要参数获取
    需要获取的参数是提供给 Druid 数据库连接池对象使用
     */
    static {
        // 利用 JdbcUtils.class 获取类加载器,在加载任务的目录中,找寻指定文件名称的文件,并且得到对应的输入流对象
        InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
        // 创建 Properties 用于存储和获取 druid.properties 文件内容
        Properties properties = new Properties();

        try {
            // 通过文件输入流 加载对应文件内容
            properties.load(in);

            // 【核心】 利用 Druid 数据库连接池工厂类,创建数据库连接池对象,参数是 Properties 对象
            pool = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                assert in != null;
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * JdbcUtils 工具类获取数据库连接对象方法,简化操作流程,获取数据库连接对象
     * 必要参数为当前 JdbcUtils 工具类的成员变量,可以在方法内部使用,用户执行
     * getConnection 无需传入参数信息
     *
     * @return java.sql.Connection 数据库连接对象,如果获取操作失败返回 null
     */
    public static Connection getConnection() {
        Connection connection = null;

        try {
            connection = pool.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return connection;
    }

    /**
     * 获取数据库连接池对象,提供给其他类对象使用
     *
     * @return javax.sql.DataSource 数据库连接池对象
     */
    public static DataSource getDataSource() {
        return pool;
    }
    /**
     * 关闭数据库连接 java.sql.Connection 对象
     *
     * @param connection java.sql.Connection 数据连接对象
     */
    public static void close(Connection connection) {
        close(null, null, connection);
    }

    /**
     * 关闭数据库连接 java.sql.Connection 对象和数据库 SQL 语句搬运工 java.sql.Statement 对象
     *
     * @param connection java.sql.Connection 数据库连接对象
     * @param statement  java.sql.Statement 数据库SQL语句搬运工对象
     */
    public static void close(Connection connection, Statement statement) {
        close(null, statement, connection);
    }

    /**
     * 关闭数据库连接 java.sql.Connection 对象,数据库 SQL 语句搬运工 java.sql.Statement  对象
     * 和 数据库查询结果就 java.sql.ResultSet 对象
     *
     * @param connection java.sql.Connection 数据库连接对象
     * @param statement  java.sql.Statement 数据库SQL语句搬运工对象
     * @param resultSet  java.sql.ResultSet 数据库查询结果集对象
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        /*
        Connection  close 方法来自于 interface AutoCloseable
        Statement   close 方法来自于 interface AutoCloseable
        ResultSet   close 方法来自于 interface AutoCloseable
            1. 都有 close 方法!!!
            2. 他们是不是都是数据库相关的!!!
         */

        close(resultSet, statement, connection);
    }

    /**
     * 私有化 close 方法,处理关闭数据库操作相关资源,数据操作为不定长参数,底层代码方式为数组形式。
     * 所有的数据库相关资源都是 AutoCloseable 接口的实现类,可以利用多态思想,整合所有资源,统一关闭
     * 处理
     *
     * @param source AutoCloseable 可关闭资源的不定长参数。
     */
    private static void close(AutoCloseable... source) {
        /*
         数组也可以搞 Stream 流,通过 Arrays 数组工具类,调用 stream(T[] t) 获取 Stream 流对象
         这才是现在的代码风格,真的没有 if 和 for
        */
        Arrays.stream(source).filter(Objects::nonNull).forEach(s-> {
            try {
                s.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

    }
}

posted @ 2022-05-16 23:54  qtyanan  阅读(93)  评论(0编辑  收藏  举报