学习Java53天,JDBC中工具类封装v2,以及BaseDao

news/2024/5/18 23:27:18 标签: 学习, 数据库, JDBC
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
//事物时,Service和dao属于同一线程,不用再传参数了
/*
这个工具类的作用就是用来给所有的SQL操作提供“连接”,和释放连接。
这里使用ThreadLocal的目的是为了让同一个线程,在多个地方getConnection得到的是同一个连接。
这里使用DataSource的目的是为了(1)限制服务器的连接的上限(2)连接的重用性等
 */
public class JDBCTools {
    private static DataSource ds;
    private static ThreadLocal<Connection> tl = new ThreadLocal<>();
    static{//静态代码块,JDBCToolsVersion1类初始化执行
        try {
            Properties pro = new Properties();
            pro.load(ClassLoader.getSystemResourceAsStream("druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
         Connection connection = tl.get();
         if(connection  == null){//当前线程还没有拿过连接,就给它从数据库连接池拿一个
             connection = ds.getConnection();
             tl.set(connection);
         }
         return connection;
    }

    public static void free() throws SQLException {
        Connection connection = tl.get();
        if(connection != null){
            tl.remove();
            connection.setAutoCommit(true);//避免还给数据库连接池的连接不是自动提交模式(建议)
            connection.close();
        }
    }
}

基本上每一个数据表都应该有一个对应的DAO接口及其实现类,发现对所有表的操作(增、删、改、查)代码重复度很高,所以可以抽取公共代码,给这些DAO的实现类可以抽取一个公共的父类,我们称为BaseDao

针对DQL查询和非DQL进行,分成两类

public abstract class BaseDao {
    /*
    通用的增、删、改的方法
    String sql:sql
    Object... args:给sql中的?设置的值列表,可以是0~n
     */
    protected int update(String sql,Object... args) throws SQLException {
//        创建PreparedStatement对象,对sql预编译
        Connection connection = JDBCTools.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql);
        //设置?的值
        if(args != null && args.length>0){
            for(int i=0; i<args.length; i++) {
                ps.setObject(i+1, args[i]);//?的编号从1开始,不是从0开始,数组的下标是从0开始
            }
        }

        //执行sql
        int len = ps.executeUpdate();
        ps.close();
        //这里检查下是否开启事务,开启不关闭连接,业务方法关闭!
        //没有开启事务的话,直接回收关闭即可!
        if (connection.getAutoCommit()) {
            //回收
            JDBCTools.free();
        }
        return len;
    }

    /*
    通用的查询多个Javabean对象的方法,例如:多个员工对象,多个部门对象等
    这里的clazz接收的是T类型的Class对象,
    如果查询员工信息,clazz代表Employee.class,
    如果查询部门信息,clazz代表Department.class,
    返回List<T> list
     */
    protected <T> ArrayList<T> query(Class<T> clazz,String sql, Object... args) throws Exception {
        //        创建PreparedStatement对象,对sql预编译
        Connection connection = JDBCTools.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql);
        //设置?的值
        if(args != null && args.length>0){
            for(int i=0; i<args.length; i++) {
                ps.setObject(i+1, args[i]);//?的编号从1开始,不是从0开始,数组的下标是从0开始
            }
        }

        ArrayList<T> list = new ArrayList<>();
        ResultSet res = ps.executeQuery();

        /*
        获取结果集的元数据对象。
        元数据对象中有该结果集一共有几列、列名称是什么等信息
         */
         ResultSetMetaData metaData = res.getMetaData();
        int columnCount = metaData.getColumnCount();//获取结果集列数

        //遍历结果集ResultSet,把查询结果中的一条一条记录,变成一个一个T 对象,放到list中。
        while(res.next()){
            //循环一次代表有一行,代表有一个T对象
            T t = clazz.newInstance();//要求这个类型必须有公共的无参构造

            //把这条记录的每一个单元格的值取出来,设置到t对象对应的属性中。
            for(int i=1; i<=columnCount; i++){
                //for循环一次,代表取某一行的1个单元格的值
                Object value = res.getObject(i);

                //这个值应该是t对象的某个属性值
                //获取该属性对应的Field对象
//                String columnName = metaData.getColumnName(i);//获取第i列的字段名
                String columnName = metaData.getColumnLabel(i);//获取第i列的字段名或字段的别名
                Field field = clazz.getDeclaredField(columnName);
                field.setAccessible(true);//这么做可以操作private的属性

                field.set(t, value);
            }

            list.add(t);
        }

        res.close();
        ps.close();
        //这里检查下是否开启事务,开启不关闭连接,业务方法关闭!
        //没有开启事务的话,直接回收关闭即可!
        if (connection.getAutoCommit()) {
            //回收
            JDBCTools.free();
        }
        return list;
    }

    protected <T> T queryBean(Class<T> clazz,String sql, Object... args) throws Exception {
        ArrayList<T> list = query(clazz, sql, args);
        if(list == null || list.size() == 0){
            return null;
        }
        return list.get(0);
    }
}


http://www.niftyadmin.cn/n/5214582.html

相关文章

vue-router的使用技巧

一、安装 npm install vue-router 二、引入 main.ts引入 import { createApp } from vue import App from ./App.vue import router from ./routerconst app createApp(App)app.use(router) app.mount(#app)三、定义路由文件 路由的参数 meta添加路由的其他参数 redire…

在vue或者react或angular中,模板表达式中的箭头函数是无效的吗?为什么无效?

出现此问题的背景&#xff1a; 我在Angular项目中对一个标签属性绑定了一个箭头函数&#xff0c;编译报错。 在vue或者react或angular中&#xff0c;模板表达式中的箭头函数是无效的吗&#xff1f; 在 Vue、React 或 Angular 中&#xff0c;模板表达式中的箭头函数是无效的。…

Javaweb之前端工程化的详细解析

3 前端工程化 3.1 前端工程化介绍 我们目前的前端开发中&#xff0c;当我们需要使用一些资源时&#xff0c;例如&#xff1a;vue.js&#xff0c;和axios.js文件&#xff0c;都是直接再工程中导入的&#xff0c;如下图所示&#xff1a; 但是上述开发模式存在如下问题&#xff…

ENVI中给影像添加坐标系

目录 待匹配影像坐标系信息参考影像坐标信息通过参考影像匹配坐标系 当我们在ENVi中打开影像发现缺失坐标系的时候&#xff0c;可以非常方便地通过参考影像来对其进行坐标系的匹配。 待匹配影像坐标系信息 首先我们双击想要加坐标系的影像查看Metedata&#xff0c;发现此时影像…

Openwrt linux 启动流程

OpenWRT 启动流程 内核启动过程&#xff1a;【/init/mian.c】 Uboot --> start_kernel() --> rest_init() --> kernel_thread(kernel_init) --> kernel_init_freeable() 初始化过程&#xff1a; Linux Kernel(kernel_init) --> /etc/preinit --> /sbin/in…

算法设计与实现--分治篇

什么是分治算法 分治算法是一种常见的问题解决方法&#xff0c;它将一个复杂的问题划分为多个相同或相似的子问题&#xff0c;然后递归地解决这些子问题&#xff0c;最后将子问题的解合并得到原问题的解。 分治算法通常包含三个步骤&#xff1a; 分解&#xff08;Divide&…

云计算学习哪些技术

1. 虚拟化技术 虚拟化是云计算的基础&#xff0c;因此了解虚拟化技术至关重要。学习虚拟化技术时&#xff0c;需要掌握以下知识点&#xff1a; - 操作系统虚拟化&#xff1a;了解基于宿主机和客户机的虚拟化技术&#xff0c;如VMware、Hyper-V等。 - 容器化技术&#xff1a;学习…

External model DLL ”ADC083XDLL“ not found_proteus仿真报错解决方法

仿真运行报错 External model DLL ”ADC083XDLL“ not found 原因 是proteus仿真软件缺少ADC083X.DLL文件或者ADC083X.DLL文件损坏。 解决方法 1.下载没问题的ADC083x.DLL ADC083X.DLL下载链接&#xff1a; 2.找到库文件夹&#xff0c;替换库文件ADC083X.DLL 库文件夹位置…