BaseDao封装JavaWeb的增删改查

目录

什么是BaseDao?

为什么需要BaseDao?

BaseDao的实现逻辑

什么是BaseDao?

Basedao 是一种基于数据访问对象(Data Access Object)模式的设计方法。它是一个用于处理数据库操作的基础类,负责封装数据库访问的底层操作,提供通用的数据库访问方法。

Basedao 主要用于简化数据库操作的代码开发,并提供一致性可维护性。它通常包含有对数据库的增加、删除、修改和查询等操作方法,以及一些基本的事务处理功能。

Basedao 可以通过继承来扩展具体的数据库操作方法,使得在具体的业务实现中可以更加专注于业务逻辑的实现,而不需要关注底层数据库的细节。

通过使用 Basedao,开发人员可以更加高效地进行数据库操作的开发,减少了重复的代码编写,提高了代码的可维护性可读性

为什么需要BaseDao?

BaseDao 的优点包括:

  1. 代码复用(共性抽取):BaseDao 封装了常见的数据库操作方法,可以被不同的业务逻辑类多次调用,避免了重复编写相同的数据库操作代码,提高了代码的复用性。
  2. 提高开发效率:BaseDao 提供了高级的数据库操作方法,开发人员可以直接调用这些方法,减少了重复的开发工作,提高了开发效率。
  3. 降低代码耦合度:BaseDao 封装了底层数据库的细节,通过调用 BaseDao 的方法,业务逻辑类可以和具体的数据库实现解耦,减少了业务逻辑类和数据库之间的直接依赖,提高了代码的可维护性和可扩展性。
  4. 提供事务支持:BaseDao 通常会提供事务处理的功能,可以保证数据库操作的一致性。开发人员可以通过 BaseDao 来处理事务,确保在一次操作中,要么全部成功,要么全部失败,避免了数据不一致的情况。

总的来说,BaseDao 通过封装数据库操作,提供高级的数据库操作方法,降低代码耦合度,提供事务支持等优点,可以提高开发效率,简化数据库操作,提高代码的可维护性和可扩展性。

BaseDao的实现逻辑

简单来说BaseDao就是对数据库底层操作业务进行共性抽取,下面就以学生信息为例~

1、在学生信息管理系统中,不论增删改查还是特殊业务都离不开每次访问数据库的配置驱动以及获取连接关闭连接,所以这两步是必然封装的

/**
 * 获取数据库连接对象
 */
public Connection getConnection() throws Exception {  //获取连接对象方法
    //加载配置文件
    Properties properties = new Properties();
    properties.load(Files.newInputStream(Paths.get("D:\\druid.properties")));

    //创建一个指定参数的数据库连接池
    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    return dataSource.getConnection();  //返回连接对象
}

因为当时博主访问数据库是采用Druid连接池,所以配置驱动就使用配置文件的方式,配置文件( .properties )代码如下:

driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/student?useServerPrepStmts=true
username = root
password = root
initialSize = 10
maxActive = 30
maxWait = 1000

关闭连接方法封装代码如下:

/**
 * 关闭数据库连接
 * @param conn 数据库连接
 * @param stmt PreparedStatement预处理对象
 * @param rs 结果集
 */
public void closeAll(Connection conn, PreparedStatement stmt, ResultSet rs) {  //关闭连接方法
        // 若结果集对象(RresuleSet)不为空,则关闭
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 若预处理对象(PreparedStatement)不为空,则关闭
        if (stmt != null) {
            try {
                stmt.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 若数据库连接对象(Connection)不为空,则关闭
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2、通过第一步的调用能够返回一个连接对象,那么接下来就可以进行基本的增删改查操作, 增删改都属于对数据做更新,所以先做增删改

/**
 * 增、删、改的操作
 * @param preparedSql 预编译的 SQL 语句
 * @param param 参数的字符串数组
 * @return 影响的行数
 */
public int updateRow (String preparedSql, Object[] param) throws Exception {  //增删改操作的方法
    PreparedStatement preparedStatement = null;  //创建预处理对象并初始为空(通过预处理可以防止SQL恶意注入)
    int row = 0;  //初始受影响行数(当受影响行数大于0时,说明执行成功数据则更新)
    Connection connection = getConnection();  //调用getConnection()方法获取数据库连接
    try {
        preparedStatement = connection.prepareStatement(preparedSql);  //对sql形参预处理
        if (param != null) {  //形参数组(注入参数)不为空时,循环遍历对预处理sql注入参数
            for (int i = 0; i < param.length; i++) {
                //为预编译sql设置参数
                preparedStatement.setObject(i + 1, param[i]);
            }
        }
        row = preparedStatement.executeUpdate();  //执行sql语句并得到受影响的行数
        closeAll(connection,preparedStatement,null);  //调用closeAll()方法关闭资源,因为执行操作不含查询,则将结果集的实参传空
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return row;  //返回受影响行数
}

因为sql语句中需要的参数类型是不确定的,则用Object类型数组作为容器

3、至此就剩查询操作了,在封装前需要创建一个实体类,以至于后续每个实体类都可以代表为一行数据,代码如下:

public class Student {
    //初始字段
    private int id;
    private String name;
    private int age;

    public Student(int id, String name, int age) {  //构造函数
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {  //toString方法
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

实体对象有了,那么走你:

public List<Student> queryData (String sql, Object[] param) throws Exception {  //查询操作的方法
    PreparedStatement preparedStatement = null;  //创建预处理对象并初始为空(通过预处理可以防止SQL恶意注入)
    Connection connection = getConnection();  //调用getConnection()方法获取数据库连接
    preparedStatement = connection.prepareStatement(sql);  //调用getConnection()方法获取数据库连接
    if (param != null) {  //形参数组(注入参数)不为空时,循环遍历对预处理sql注入参数
        for (int i = 0; i < param.length; i++) {
            //为预编译sql设置参数
            preparedStatement.setObject(i + 1, param[i]);
        }
    }
    ResultSet resultSet = preparedStatement.executeQuery();  //得到返回的结果集
    List<Student> list = new ArrayList<Student>();  //创建List接口对象,泛型为指定Student对象类型,代表每个实体对象都是一行数据
    while (resultSet.next()) {  //循环遍历结果集,将每行数据封装成Student对象,并添加到List集合中
        Student student= new Student(resultSet.getInt(1), resultSet.getString(2), resultSet.getInt(3));  //获取结果集中的数据存入Student对象中
        list.add(student);  //将Student对象存入list接口中
    }
    closeAll(connection,preparedStatement,resultSet);  //调用closeAll()方法关闭数据库连接
    return list;  //返回List集合对象 
}

接下来创建一个测试类进行检查:

1、增删改测试

//增删改测试
BaseDao baseDao = new BaseDao();  //创建BaseDao对象
String sql = "insert into student(id,name,age) values(?,?,?)";  //定义预处理sql
Object[] list = {6, "老八", 35};  //将sql需要的参数存入至Object类型的数组
int add = baseDao.updateRow(sql, list); //调用增删改的方法并接收返回的受影响行数
if (add > 0) {  //受影响行数大于0则说明数据更新成功
    System.out.println("新增成功!受影响行数:" + add);
}
/* 删除、修改也是一样 */

控制台:

2、查询测试 

//查询测试
BaseDao baseDao = new BaseDao();  //创建BaseDao对象
String sql = "select * from student";  //定义预处理sql
List<Student> list = baseDao.queryData(sql, null);  //创建List接口,泛型为Student对象类型,用于存储查询返回的数据
for (Student student : list) {
    System.out.println(student.getId() + "\t\t" + student.getName() + "\t\t" + student.getAge());  //输出数据
}

控制台:

这么一来,JavaWeb中的每次增删改查都可以简明的实现,增删改查以外的特殊性业务功能可在BaseDao对象中具体实现方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/494279.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不显示excel中零值方法

excel中想让数字0不显示的方法如下&#xff1a; √去掉则数字格式0不再显示 。若找不到此项&#xff0c;运行以下代码即可&#xff1a; Sub 去除excel中零值() ActiveWindow.DisplayZeros False 不显示零值 End Sub altf11打开vba idea&#xff0c;插入->模块&#xff…

多维数组和交错数组笔记

1.) 关于数据的几个概念&#xff1a; Rank&#xff0c;即数组的维数&#xff0c;其值是数组类型的方括号之间逗号个数加上1。 Demo&#xff1a;利用一维数组显示斐波那契数列F(n) F(n-1) F(n-2) (n >2 ),每行显示5项,20项. static void Main(string[] args){int[] F n…

C++初学者:像C#一样优雅写程序

C语言的强大&#xff0c;在于自由自在&#xff0c;你可以随便怎么写程序&#xff0c;不讲格式&#xff0c;可以很整齐&#xff0c;也可以鬼画符&#xff0c;只要能运行就可以了&#xff0c;程序员可以自由发挥。 如图&#xff1a; 国际C语言大赛中的代码 图2 C的语言更强大&…

机器人深度学习IMU和图像数据实现焊接精细操作

在双电极气体保护金属弧焊 &#xff08;DE-GMAW&#xff09; 中&#xff0c;对焊枪和旁路电极位置的精确控制是至关重要的。为了这一过程&#xff0c;科研团队提出了安装微型惯性测量单元&#xff08;IMU&#xff09;传感器和摄像头&#xff0c;来记录焊工控制焊枪的移动和微调…

pyhive入门介绍和实例分析(探索票价与景点评分之间是否存在相关性)

介绍 PyHive 是一组 Python DB-API 和 SQLAlchemy 接口&#xff0c;可用于 Presto 和 Hive。它为 Python 提供了一个与 Presto 和 Hive 进行交互的平台&#xff0c;使得数据分析师和工程师可以更方便地进行数据处理和分析。 以下是使用 PyHive 进行数据分析时需要注意的几点&…

Vue时间组件:Dayjs与Moment对比

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

FFmpeg初步了解

一、了解FFmpeg 1.1 什么是FFmpeg FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec&#xff0c;为了保证…

07_Response

文章目录 案例&#xff08;请求分发案例&#xff09; Response响应行响应头响应体特殊响应头refreshContent-typeContent-dispositionlocation 案例&#xff08;登录案例&#xff09; 案例&#xff08;请求分发案例&#xff09; 场景&#xff1a;有多个请求 Http://localhost:…

python Flask扩展:如何查找高效开发的第三方模块(库/插件)

如何找到扩展以及使用扩展的文档 一、背景二、如何寻找框架的扩展&#xff1f;三、找到想要的扩展四、找到使用扩展的文档五、项目中实战扩展 一、背景 刚入门python的flask的框架&#xff0c;跟着文档学习了一些以后&#xff0c;想着其实在项目开发中&#xff0c;经常会用到发…

设计模式之建造者模式精讲

也叫生成器模式。将一个复杂的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 在建造者模式中&#xff0c;有如下4个角色&#xff1a; 抽象建造者&#xff08;Builder&#xff09;&#xff1a;用于规范产品的各个组成部分&#xff0c;并进行抽象&…

HTTP请求走私!!!(一)

想都是问题&#xff0c;做才是答案 什么是请求走私&#xff1f; HTTP请求走私是针对于服务端处理一个或者多个接收http请求序列的方式&#xff0c;进行绕过安全机制&#xff0c;实施未授权访问一种攻击手段&#xff0c;获取敏感信息&#xff0c;并直接危害其他用户。 Web 应用…

集合系列(十五) -CopyOnWriteArrayList详解

一、摘要 在介绍 CopyOnWriteArrayList 之前&#xff0c;我们一起先来看看如下方法执行结果&#xff0c;代码内容如下&#xff1a; public static void main(String[] args) {List<String> list new ArrayList<String>();list.add("1");list.add(&quo…

RabbitMQ(简单模式)

2种远程服务调用 1openFeign&#xff1a; 优点&#xff1a;能拿到被调用的微服务返回的数据&#xff0c;系统系耦度高&#xff0c;系统稳定。 缺点&#xff1a;同步调用&#xff0c;如果有很多服务需要被调用&#xff0c;耗时长。 MQ,消息队列&#xff0c;RabbitMQ是消息we…

windows DNS 服务器常用配置

Windows Server 上的 DNS 服务器配置主要包括以下步骤和常见设置&#xff1a; 安装 DNS 服务 打开服务器管理器&#xff0c;在 "角色和功能" 添加或删除角色中安装 DNS 服务器角色。 配置 DNS 服务器基础设置 添加 DNS 区域&#xff1a; 在 DNS 管理器中&#xff…

WPF 窗体样式 WindowStyle 设置 none, 如何移动窗体

当窗体样式设为None时&#xff0c;因为标题栏被隐藏&#xff0c;我们无法移动窗体&#xff0c;为了使窗体可以移动&#xff0c;我们要为window中的布局控件添加MouseDown事件的事件处理器&#xff0c;并且要为其设置一个背景(window设置为允许透明&#xff0c;当grid没有背景时…

书籍推荐|meta分析R语言实践教程-Doing Meta-Analysis with R: A Hands-On Guide

“The problems are solved, not by giving new information, but by arranging what we have known since long.” – Ludwig Wittgenstein 推荐理由 《Doing Meta-Analysis with R: A Hands-On Guide》是由 Mathias Harrer, Pim Cuijpers, Toshi Furukawa, 和 David Ebert所…

Hides for Mac:应用程序隐藏工具

Hides for Mac是一款功能强大的应用程序隐藏工具&#xff0c;专为Mac用户设计。它能够帮助用户快速隐藏当前正在运行的应用程序窗口&#xff0c;保护用户的隐私和工作内容&#xff0c;避免不必要的干扰。 软件下载&#xff1a;Hides for Mac下载 Hides for Mac的使用非常简单直…

Windows下载使用nc(netcat)命令

‘nc’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff1f; 点击链接地址&#xff0c;下载压缩包。 完成后解压 使用方式&#xff08;三种&#xff09;&#xff1a; 1、直接双击exe使用 2、把这个exe放到cmd启动的默认路径下 放到默认路径下&#xff0c;使用nc&a…

0.96寸OLED屏调试 ----(一)

所需设备&#xff1a; 1、USB 转 SPI I2C 适配器&#xff1b;内附链接 2、0.96寸OLED显示模块&#xff1b; 备注&#xff1a;专业版、升级版都适用&#xff1b; 首先介绍一下OLED显示模块&#xff0c;SSD1306是一款OLED驱动芯片&#xff0c;拥有最大128*64像素支持&#xff…

亚马逊云科技:基于老服务器打造的旧实例类型

内容摘要&#xff1a; 2021年&#xff0c;距离第一个EC2实例上线已经十五周年了。 在漫长的开发过程中&#xff0c;很多EC2实例自然会基于旧服务器构建。 随着时间的推移&#xff0c;旧的服务器总是需要更换硬件&#xff0c;实例也得更换&#xff0c;但并不是所有的用户都想迁…
最新文章