2022-08-20 第二小组 张明旭 JDBC学习记录

目录

心情日记

重点归纳

数据库连接池

Druid(德鲁伊)连接池

Hikari(光)连接池

DBUtils工具包下的QueryRunner

封装通用的数据库操作类

知识点

数据库连接池

JDBC使用数据库连接池的必要性

“池化思想”

常见连接池的数据包、技术栈

Druid(德鲁伊)连接池

在项目中导入德鲁伊连接池的包

 再写一个druid的属性文件

封装德鲁伊连接池

应用德鲁伊连接池获取连接

应用

Hikari连接池

在项目中导入Hikari连接池的包(需要四个)

 再写一个Hikari的属性文件

封装通用的数据库操作类(泛型的应用)

通用的数据库操作的接口

通用的数据库操作的接口的实现类

一种方便的半自动封装类:DBUtil工具包

导包

 应用

封装通用的数据库操作类


心情日记

这几天学的JDBC如果标准没那么严格的话还挺轻松,能看懂、记住连接数据库流程基本就可以了,可以靠CV大法写代码,但是感觉自己写的代码如果有的地方自己都不懂,就感觉不是我写的一样,可是学又学不会。。。。。。

重点归纳

数据库连接池

        Druid(德鲁伊)连接池

       Hikari(光)连接池

DBUtils工具包下的QueryRunner

封装通用的数据库操作类

知识点

数据库连接池

connection是一种稀有资源,难获取,一个连接的建立就创造了一个资源

例如:QQ如果连上了,n那么QQ和腾讯的服务器就姜丽丽一个连接,有代价:在线人数过多,服务器就会崩溃
解决方案:
1.服务器就一个人用
2.限定服务器人数,超出固定人数的人想要进入服务器需要排队。

JDBC使用数据库连接池的必要性

在使用基于Web程序的数据库连接是不能关的
1.在主程序中建立连接
2.执行sql
3.断开连接

所有的JDBC连接通过DriverManager.getConnection获取
用完的连接不要被垃圾回收,能够重复利用

“池化思想”

每次去初始化一个连接池,连接池中会有很多个连接等待使用
使用完连接之后,不需要关闭连接,只需要把连接还回到连接池中
而且还连接的操作不需要手动操作

例如:
初始化连接:10个链接,有20个请求,10个请求直接拿走10个连接去办事,剩下的10个请求再向服务器申请连接数
设置一些属性,一段时间后自动删除连接池中多余连接数

常见连接池的数据包、技术栈


1.C3P0:2代数据库连接池,太老了不学
2.DBCP:2代数据库连接池,太老了不学
3.Druid:(德鲁伊)数据库连接池,最好用的连接池
    阿里巴巴开源平台上的一个数据库连接池实现,整合了C3P0和DBCP各自的优点,
    加入了日志监控,可以监控sql语句的执行情况
4.Hikari(光):目前最快的连接池,springboot默认的连接池

主要学后两者;根据使用情况挑选使用
.properties
约定大于配置大于编码

Druid(德鲁伊)连接池

在项目中导入德鲁伊连接池的包

项目需要所有的导包在一个文件下(新建lib文件)

 在此文件下粘贴两个包:druid的jar包,mysql的jar包

 再写一个druid的属性文件

要求:前缀为druid

druid.url=jdbc:mysql://127.0.0.1:3306/practice?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
druid.username=root
druid.password=root
druid.driverName=com.mysql.cj.jdbc.Driver

druid.initialSize=10
druid.maxActive=20
druid.maxWait=20

封装德鲁伊连接池

public class BaseDao {  
public static final DataSource DATA_SOURCE;

    static {
        Properties properties = new Properties();
        try {
            properties.load(BaseDao.class.getClassLoader().getResourceAsStream("druid.properties"));
            // 创建德鲁伊的数据源
            DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void release(Statement stmt, ResultSet rs) {
        if(Objects.nonNull(stmt)) {
            try {
                stmt.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(Objects.nonNull(rs)){
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

应用德鲁伊连接池获取连接

  @Test
    public void test01() throws IOException, SQLException {
        Properties properties = new Properties();
        properties.load(Ch01.class.getClassLoader().getResourceAsStream("druid.properties"));

        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.configFromPropety(properties);

        System.out.println(druidDataSource.getConnection());
        System.out.println(druidDataSource.getCreateCount());

    }

应用

    @Test
    public void test01() {
        try {
            Connection connection = BaseDao.DATA_SOURCE.getConnection();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

Hikari连接池

在项目中导入Hikari连接池的包(需要四个)

 

 再写一个Hikari的属性文件

要求:driverName变为driverClassName,无前缀

jdbcUrl=jdbc:mysql://127.0.0.1:3306/practice?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username=root
password=root
driverClassName=com.mysql.cj.jdbc.Driver

其他步骤同druid。。。

封装通用的数据库操作类(泛型的应用)

1.通用的数据库操作的接口

2.该接口的实现类

以后开发中一个表一个类。

使用自己建立的接口也有约定:

1.表名和类型必须相同

2.表的字段名和类的属性名必须相同

通用的数据库操作的接口

public interface IBaseDao<T> {

    /**
     * 获取连接的方法
     */
    Connection getConnection();

    /**
     * 关闭资源
     */
    void closeAll(Statement statement, ResultSet resultSet);

    /**
     * 通用的保存
     */
    void save(Object object);

    /**
     * 通用的查询所有
     */
    List<T> findAll(Class clazz);

    /**
     * 通用的更新的方法
     */
    void update(Object obj,String fieldName,Object fieldValue);

    /**
     * 通用的删除
     */
    void delete(Class clazz,String fieldName,Object fieldValue);


    /**
     * 查询单条数据
     */
    T findOne(Class clazz,String fieldName,Object fieldValue);
}

通用的数据库操作的接口的实现类

public class BaseDaoImpl<T> implements IBaseDao<T> {
    private static final DataSource DATA_SOURCE;

    static {
        Properties properties = new Properties();
        try {
            properties.load(Ch01.class.getClassLoader().getResourceAsStream("druid.properties"));
            // 创建德鲁伊的数据源
            DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Connection getConnection() {
        try {
            return DATA_SOURCE.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public void closeAll(Statement stmt, ResultSet rs) {
        if (Objects.nonNull(stmt)) {
            try {
                stmt.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (Objects.nonNull(rs)) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }


    public void save(Object object) {
        // insert into user(id,username,password) values (?,?,?)
        Class clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();

        // 拼接出一个insert语句
        StringBuilder strb = new StringBuilder("insert into ");
        // insert into user
        String[] split = clazz.getName().split("\\.");
        strb.append(split[split.length - 1]);
        strb.append(" (");
        for (Field field : fields) {
            strb.append(field.getName().toLowerCase()).append(",");
        }
        // insert into user (id,username,password
        strb.deleteCharAt(strb.length() - 1);
        strb.append(") values (");
        for (Field field : fields) {
            strb.append("?,");
        }
        strb.deleteCharAt(strb.length() - 1);
        strb.append(")");

        PreparedStatement pstmt = null;

        try {
            Connection conn = DATA_SOURCE.getConnection();
            pstmt = conn.prepareStatement(strb.toString());

            // 给?赋值
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                pstmt.setObject(i + 1, fields[i].get(object));
            }

            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } finally {
            closeAll(pstmt, null);
        }
    }

    public List<T> findAll(Class clazz) {
        // 拼sql
        // select id,username,password from user
        // 其中id,username,password可变的他们都是一个类的属性
        List<T> list = new ArrayList<>();
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        // 利用反射获取属性名
        Field[] fields = clazz.getDeclaredFields();
        // 拼装sql语句,拼字符串
        StringBuilder fieldStr = new StringBuilder();
        fieldStr.append("select ");
        for (Field field : fields) {
            // id,username,password,
            fieldStr.append(field.getName().toLowerCase()).append(",");
        }
        // select id,username,password
        fieldStr.deleteCharAt(fieldStr.length() - 1);
        fieldStr.append(" from ");
        // select id,username,password from
        //
        String clazzName = clazz.getName().toLowerCase();
        System.out.println(clazzName + "--------------------");
        String[] split = clazzName.split("\\.");
        fieldStr.append(split[split.length - 1]);
        // select id,username,password from user
        Connection conn = getConnection();
        try {
            pstmt = conn.prepareStatement(fieldStr.toString());
            rs = pstmt.executeQuery();
            while (rs.next()) {
                // 1. 创建对象
                Object obj = clazz.getDeclaredConstructor().newInstance();
                for (Field field : fields) {
                    Object value = rs.getObject(field.getName());
                    // 访问私有化的结构
                    field.setAccessible(true);
                    // 利用反射给属性赋值,赋不上值
                    // 因为属性一定是private
                    field.set(obj, value);
                }
                list.add((T) obj);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } finally {
            closeAll(pstmt, rs);
        }

        return list;
    }


    //通用的修改
    @Override
    public void update(Object obj, String fieldName, Object fieldValue) {
        PreparedStatement pstmt = null;

        Class clazz = obj.getClass();

        // 拼接出一个update语句
        // update user set
        StringBuilder strb = new StringBuilder("update " + clazz.getName().toLowerCase().substring(clazz.getName().lastIndexOf(".") + 1) + " set ");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            // update user set username = ?,password = ?,
            strb.append(field.getName()).append(" = ").append("?").append(",");
        }
        strb.deleteCharAt(strb.length() - 1);
        // update user set username = ?,password = ?
        strb.append(" where ").append(fieldName).append("=").append(fieldValue);
//        System.out.println(strb.toString());
        try {
            Connection conn = DATA_SOURCE.getConnection();
            pstmt = conn.prepareStatement(strb.toString());
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                pstmt.setObject(i + 1, fields[i].get(obj));
            }
            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } finally {
            closeAll(pstmt, null);
        }
    }

    //通用的删除
    @Override
    public void delete(Class clazz, String fieldName, Object fieldValue) {
        // 拼接一个delete语句
        PreparedStatement pstmt = null;
        StringBuilder sql = new StringBuilder("delete from ");
        // delete from user
        sql.append(clazz.getName().toLowerCase().substring(clazz.getName().lastIndexOf(".") + 1));
        sql.append(" where ").append(fieldName).append(" = ?");
        try {
            Connection conn = DATA_SOURCE.getConnection();
            pstmt = conn.prepareStatement(sql.toString());
            pstmt.setObject(1, fieldValue);

            pstmt.executeUpdate();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            closeAll(pstmt, null);
        }
    }

    //查询某一条记录
    @Override
    public T findOne(Class clazz, String fieldName, Object fieldValue) {
        T t = null;

        PreparedStatement pstmt = null;
        ResultSet rs = null;

        // 拼接一个select语句
        Field[] fields = clazz.getDeclaredFields();
        StringBuilder strb = new StringBuilder();
        strb.append("select ");
        for (Field field : fields) {
            strb.append(field.getName().toLowerCase()).append(",");
        }
        strb.deleteCharAt(strb.length() - 1);
        // select id,username,password
        strb.append(" from ");
        strb.append(clazz.getName().toLowerCase().substring(clazz.getName().lastIndexOf(".") + 1));
        // select id,username,password from user
        strb.append(" where ");
        strb.append(fieldName).append("= ?");
        // select id,username,password from user where id = ?
        try {
            Connection conn = DATA_SOURCE.getConnection();
            pstmt = conn.prepareStatement(strb.toString());
            pstmt.setObject(1, fieldValue);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                Object o = clazz.getDeclaredConstructor().newInstance();
                for (Field field : fields) {
                    Object value = rs.getObject(field.getName());
                    field.setAccessible(true);
                    field.set(o, value);
                }
                t = (T) o;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        return t;
    }
}

一种方便的半自动封装类:DBUtil工具包

 使用的是DBUtils工具包下的一个类:QueryRunner

导包

 应用

public class Ch01 {
    @Test
    public void test03() throws SQLException {

//QueryRunner类穿的参数是数据源
        QueryRunner runner = new QueryRunner(BaseDao.DATA_SOURCE);
        int i = runner.update("update teacher set name = ? where id = ?", "mmm", 6);
        System.out.println(i);

    }

    /**
     * 查询一个记录
     */
    @Test
    public void test02() throws SQLException {
        QueryRunner runner = new QueryRunner(BaseDao.DATA_SOURCE);
        Teacher teacher = runner.query("select * from teacher where id = ?", new BeanHandler<>(Teacher.class), 1);
        System.out.println(teacher);
    }

    /**
     * 查询多个记录
     */
    @Test
    public void test01() throws SQLException {
        // 要使用DBUtils使用的是一个类
        // 传入的是一个数据源DataSource,不是一个Connection
        QueryRunner runner = new QueryRunner(BaseDao.DATA_SOURCE);

        // 查询多个记录
        //传的参数为类---是把查询的结果封装参数类,不用自己封转了
        //之前几十行代码完成的任务在这工具包、工具类下三行代码完成
        List<Teacher> teachers = runner.query("select * from teacher", new BeanListHandler<>(Teacher.class));
        System.out.println(teachers);
    }
}

封装通用的数据库操作类

1.接口

2.接口的实现类

接口

import java.sql.SQLException;
import java.util.List;

public interface DAO<T> {

    /**
     * 更新
     * @return
     */
    int update(String sql,Object ... args) throws Exception;

    /**
     * 通用的查询所有
     */
    List<T> getForList(String sql,Object... args) throws Exception;

    /**
     * 通用的查询单个
     */
    T get(String sql,Object...args) throws Exception;

    /**
     * 查询某一个列的值,统计
     */
    <E> E getForValue(String sql,Object ... args) throws SQLException;

}

实现类

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

public class DAOImpl<T> implements DAO<T> {

    private QueryRunner runner = null;
    private Class<T> type;

    /**
     * 这个构造器中在做的事:
     *  为了获取Class<T> type = Teacher.class
     */
    public DAOImpl() {
        runner = new QueryRunner(JDBCUtil.getDataSource());
        // 获得当前类的带有泛型类型的父类(运行期this其实是DAOImpl的某个子类)
        ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
        type = (Class<T>) ptClass.getActualTypeArguments()[0];
    }

    @Override
    public int update(String sql, Object... args) throws Exception {
        return runner.update(sql,args);
    }

    @Override
    public List<T> getForList(String sql, Object... args) throws Exception {
        return runner.query(sql,new BeanListHandler<>(type),args);
    }

    @Override
    public T get(String sql, Object... args) throws Exception {
        return runner.query(sql,new BeanHandler<>(type),args);
    }

    @Override
    public <E> E getForValue(String sql, Object... args) throws SQLException {

        return (E) runner.query(sql,new ScalarHandler<>(),args);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值