三层架构实现增删改查操作封装

2023-11-14

概要

三层架构 
三层架构分为:数据(dao)层、 业务(service)层、控制(controller)层

(1)表示层(USL,即User Show Layer):视图层
    a. 前台:对应于MVC中的View,用于和用户交互、界面的显示。
    b. 对应于MVC中的Controller,用于控制跳转、调用业务逻辑层。
(2)业务逻辑层(BLL,即Business Logic Layer):Service层
    a. 接收表示层的请求及调用
    b. 组装数据访问层
(3)数据访问层(DAL,即Data Access Layer):Dao层
    直接访问数据库的操作

整体架构流程

代码顺序:

1.数据库表

2.实体层

3.dao层、daoimpl

4.service层、serviceimpl

5.controller层

就像搭房子,又下往上,像领导向下调用。controller层调用service层,再由service调用dao层。

技术名词解释

三层架构来源于后端开发的一种分层的思想。

引用自百科的解释:

三层架构(3-tier architecture)通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。

区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。

各层的作用如下:

表示层:主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。
业务逻辑层:主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。
数据访问层:主要看数据层里面有没有包含逻辑处理,实际上它的各个函数主要完成各个对数据文件的操作。而不必管其他操作。

 

技术细节

一.案例(JSP连接MySQL数据库并实现增删改查)

1.代码目录

 2.应用的MySQL数据库中的表(包含username和password,后面也只会用到这两个):

3.代码介绍

(1)先要写的是pojo包中的Dept类和Emp类,最后写User类

package com.hp.pojo;

public class Dept {
    private int did;
    private String dname;
    private String dlocation;
    private String leader;

    public static void main(String[] args) {
        System.out.println(new Dept());
    }
    @Override
    public String toString() {
        return "Dept{" +
                "did=" + did +
                ", dname='" + dname + '\'' +
                ", dlocation='" + dlocation + '\'' +
                ", leader='" + leader + '\'' +
                '}';
    }

    //有参构造
    public Dept(int did, String dname, String dlocation, String leader) {
        this.did = did;
        this.dname = dname;
        this.dlocation = dlocation;
        this.leader = leader;
    }
//无参构造
    public Dept() {
    }
    //封装

    public int getDid() {
        return did;
    }

    public void setDid(int did) {
        this.did = did;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getDlocation() {
        return dlocation;
    }

    public void setDlocation(String dlocation) {
        this.dlocation = dlocation;
    }

    public String getLeader() {
        return leader;
    }

    public void setLeader(String leader) {
        this.leader = leader;
    }
}

 

package com.hp.pojo;

import java.util.Date;

public class Emp {
    private String id;
    private String name;
    private String sex;
    private Date birth;
    private double salary;
    private int deptId;

    public Emp(String id, String name, String sex, Date birth, double salary, int deptId) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.birth = birth;
        this.salary = salary;
        this.deptId = deptId;
    }

    public Emp() {
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", birth=" + birth +
                ", salary=" + salary +
                ", deptId=" + deptId +
                '}';
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }
}

(2)接下来进行dao层的增删改查操作(这里再附带JdbcUtil,即对jdbc的封装)
package com.hp.dao.impl;

import com.hp.dao.IDeptDao;
import com.hp.pojo.Dept;
import com.hp.utils.JdbcUtil;
import com.hp.utils.JdbcUtilPlus;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/*
DeptDaoImpl:
Dept 表示操作的实体
Dao 表示执行层/数据访问层/基层
Impl 表示实现类
*/
public class DeptDaoImpl implements IDeptDao {
    @Override
    public List<Dept> list() {
        return JdbcUtil.list("select * from t_dept where did=13",Dept.class);
      }

    @Override
    public Dept selectRow(int did) {
        return JdbcUtilPlus.selectRow("select * from t_Dept where did= ?",Dept.class,did);
    }
}
//查询多行多列
public static <T> List<T> list(String sql,Class<T> c) {
    //创建一个集合,存放所有对象
    List<T> tList = new ArrayList<>();
    try {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/salary?characterEncoding=utf-8", "root", "root");
        Statement statement = conn.createStatement();
        //statement执行sql,返回结果集
        ResultSet rs = statement.executeQuery(sql);
        //结果集rs得到结果集元数据
        ResultSetMetaData md = rs.getMetaData();
        //获取结果集的总列数
        int columnCount = md.getColumnCount();
        //解析rs(循环打印)
        while (rs.next()) {//读取结果集的光标向下移动,光标默认在哪一行,列名所在的那一行
            //根据每一行的数据,封装成一个实体对象
            T t = c.newInstance();
            //1.取出某一行的每一列数据,封装到对象t的属性中
            for (int i = 1; i <= columnCount; i++) {
                //通过列的序号,获取每一列的值
                Object value = rs.getObject(i);
                if (value!=null){
                    //通过列的序号,获取每一列的列名
                    String columnName = md.getColumnName(i);
                    //因为列名和实体类t中的属性名一致,为每一个属性构造一个反射中的set方法
                    Field f = c.getDeclaredField(columnName);
                    //赋予私有属性的赋值权限
                    f.setAccessible(true);
                    //使用反射,把value给到对象t的属性中
                    f.set(t,value);//理解为:把value赋值给对象t的columnName属性,相当于set方法
                }
            }
            //把对象存入集合中
            tList.add(t);
        }
        //关闭资源
        statement.close();
        conn.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return tList;
}
//查询一行
public static <T> T selectRow(String sql,Class<T> c) {
    try {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/salary?characterEncoding=utf-8", "root", "root");
        Statement statement = conn.createStatement();
        //statement执行sql,返回结果集
        ResultSet rs = statement.executeQuery(sql);
        //结果集rs得到结果集元数据
        ResultSetMetaData md = rs.getMetaData();
        //获取结果集的总列数
        int columnCount = md.getColumnCount();
        //解析rs(循环打印)
        // 根据每一行的数据,封装成一个实体对象
        T t=null;
        if (rs.next()) {//读取结果集的光标向下移动,光标默认在哪一行,列名所在的那一行
            t = c.newInstance();
            //1.取出某一行的每一列数据,封装到对象t的属性中
            for (int i = 1; i <= columnCount; i++) {
                //通过列的序号,获取每一列的值
                Object value = rs.getObject(i);
                if (value!=null){
                    //通过列的序号,获取每一列的列名
                    String columnName = md.getColumnName(i);
                    //因为列名和实体类t中的属性名一致,为每一个属性构造一个反射中的set方法
                    Field f = c.getDeclaredField(columnName);
                    //赋予私有属性的赋值权限
                    f.setAccessible(true);
                    //使用反射,把value给到对象t的属性中
                    f.set(t,value);//理解为:把value赋值给对象t的columnName属性,相当于set方法
                }
            }
        }
        //关闭资源
        statement.close();
        conn.close();
        return t;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
//查询一列
public static <T> List<T> selectColumn(String sql,Class<T> c) {
    //创建一个集合,存放所有对象
    List<T> tList = new ArrayList<>();
    try {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/salary?characterEncoding=utf-8", "root", "root");
        Statement statement = conn.createStatement();
        //statement执行sql,返回结果集
        ResultSet rs = statement.executeQuery(sql);
        //结果集rs得到结果集元数据
        ResultSetMetaData md = rs.getMetaData();
        //获取结果集的总列数
        int columnCount = md.getColumnCount();
        //解析rs(循环打印)
        while (rs.next()) {//读取结果集的光标向下移动,光标默认在哪一行,列名所在的那一行
                //通过列的序号,获取每一列的值
                T t = (T) rs.getObject(1);
                //把对象存入集合中
                tList.add(t);
            }
        //关闭资源
        statement.close();
        conn.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return tList;
}
//查询单个
public static <T> T selectOne(String sql,Class<T> c) {
    try {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/salary?characterEncoding=utf-8", "root", "root");
        Statement statement = conn.createStatement();
        //statement执行sql,返回结果集
        ResultSet rs = statement.executeQuery(sql);
        //结果集rs得到结果集元数据
        ResultSetMetaData md = rs.getMetaData();
        //获取结果集的总列数
        int columnCount = md.getColumnCount();
        //解析rs(循环打印)
        T t=null;
        if (rs.next()){
            t = (T) rs.getObject(1);
        }
        //关闭资源
        statement.close();
        conn.close();
        return t;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
//增 删 改
public static int update(String sql) {
    try {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/salary?characterEncoding=utf-8", "root", "root");
        Statement statement = conn.createStatement();
        //statement执行sql,返回结果集
        int i = statement.executeUpdate(sql);
        //关闭资源
        statement.close();
        conn.close();
        return i;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return 0;
}

上述难度跳动比较大,涉及到反射、泛类,而且这还是没有升级后的代码,存在sql注入的问题。我们后续还需要改进代码,让代码变得更加安全简洁。需要帮助理解的可以留言私信我!我们接着往下面看

(3)是逻辑性的service包啦

package com.hp.service.impl;

import com.hp.dao.IDeptDao;
import com.hp.dao.impl.DeptDaoImpl;
import com.hp.pojo.Dept;
import com.hp.service.IDeptService;

import java.util.List;

/*
DeptServiceImpl:
Dept 操作的实体类,或者操作某个表
Service 表示业务层
Impl 表示实现类*/
public class DeptServiceImpl implements IDeptService {
    //引入dao层
    private IDeptDao deptDao=new DeptDaoImpl();
    @Override
    public int add() {
        return 0;
    }

    @Override
    public List<Dept> list() {
        return deptDao.list();
    }

    @Override
    public Dept selectRow(int did) {
        return deptDao.selectRow(did);
    }
}
因为我们都已经把实现类写出来了,所以说它的接口类很容易就能写出,这里就不一一给大家说明了

(4)最后我想给大家实现一个入口测试类,用来判断所写的功能是否实现

@Test
public void testRow(){
    Dept dept = selectRow("select * from t_Dept where did=6", Dept.class);
    System.out.println(dept);
}
@Test
public void testColumn(){
    List<String> list = selectColumn("select dname from t_Dept", String.class);
    System.out.println(list);
}
@Test
public void testOne(){
    String dname = selectOne("select dname from t_Dept where did=1", String.class);
    System.out.println(dname);
}
@Test
public void testUpdate(){
    int j = update("insert into t_Dept values (null,'a','b','c')");
    System.out.println(j);
}
@Test//测试登录
public void testLogin(){
    String username="cc'or'1'='1";
    String password="cc'or'1'='1";
    User user = selectRow("select * from t_users where username='" + username + "' and password='" + password+"'", User.class);
    System.out.println(user!=null?"登陆成功":"登录失败");
}
最后一个也是下次讲述的内容之一,这里我留一个悬念,聪明的小伙伴们也看到这里我用了@Test,注意这里要导一个包junit-4.12.jar,需要的可以私信我!有什么问题后续也可以提出来,知无不言言无不尽。

小结

本节课我们大家搭建了三层架构:控制层、业务层、数据访问层,让我们的数据在各个层之间传递,最后我们要简化代码——抽取工具类。从总结来看,我们的核心就是抽取工具类。所以我们最重要的就是理解工具类的方法,在java基础中好好学习泛类,面向对象,反射,这样在后续的java进阶学习中,才能更加如鱼得水,游刃有余!最后我们为什么要用三层架构的设计模式?这一点也困惑我许久。通过老师的讲解和自己的总结得出dao层是基层,而service是中层管理人员,最后controller是高层,一个项目需要每个人发挥自己的能力,这样反映了java编程工作团队合作的重要性。只有我们一层管理着下一层,秩序才不会紊乱,功能模块才会更加稳定。有不同见解的朋友也可以底下留言,也可以私下联系我,让我们遨游在java的海洋里面吧!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三层架构实现增删改查操作封装 的相关文章

随机推荐

  • ES 搜索21 (function_score查询 关键字 functions 和 weight 滤集提升权重分)

    过滤集提升权重 回到 忽略 TF IDF 里处理过的问题 我们希望根据每个度假屋的特性数量来评分 当时我们希望能用缓存的过滤器来影响评分 现在 function score 查询正好可以完成这件事情 到目前为止 我们展现的都是为所有文档应用
  • kubesphere多集群管理,实现kubernetes多集群同时应用部署

    文章目录 一 kubesphere集群部署 1 准备环境 2 下载kubesphere安装工具KubeKey 3 准备集群部署配置文件 4 安装集群 5 验证安装 二 配置多集群 1 打开集群tower服务的nodeport端口 2 修改主
  • Jenkins:(看起来挺好看的)邮件模板样式

    Jenkins 邮件模板样式目录导航 邮件模板样式一 根据样式三改编 背景图自定义 邮件模板样式二 邮件模板样式三 邮件模板样式四 邮件模板样式一 根据样式三改编 背景图自定义
  • Linux上安装和使用Wireshark

    CentOS下安装Wireshark相当简单 两条命令就够了 这里 主要是记录写使用方面的东西 安装 1 yum install wireshark 注意这样并无法使用wireshark命令和图形界面 但提供了抓包基本功能 2 yum in
  • Dlib库中实现正脸人脸关键点(landmark)检测的测试代码

    Dlib库中提供了正脸人脸关键点检测的接口 这里参考dlib examples face landmark detection ex cpp中的代码 通过调用Dlib中的接口 实现正脸人脸关键点检测的测试代码 测试代码如下 referenc
  • 2014年1月14日星期二(DEMO7-2,加载3D线框立方体物体模型)

    上个DEMO 是渲染列表 这个DEMO 进行了加载PLG模型 仍然是一步步地进行 PLG模型首行包含了物体名称 顶点数和多边形数3部分组成 加载模型时可以每次读取一行 并对其中的数字进行分析 现在开始进行代码 先设置摄像机坐标和位置 朝向
  • 利用cin和cout完成信息的输入输出(TOZJ练习5681)

    项目场景 问题描述 在dev c 上运行正确 在TZOJ出现Presentation Error 答案和标准结果非常接近 在输出结果中 多了或少了不必要的空格或者回车或者其他 的代码 include
  • Java集合排序

    一 概述 1 集合排序概述 数组排序 int arr 1 2 3 Arrays sort arr 集合排序 使用Collections类中 sort 方法对List集合进行排序 sort List list 根据元素的自然顺序对指定列表按升
  • 基于内容的图像检索(CBIR) ——以图搜图

    文章目录 一 实现原理 二 基于内容的图像检索的特征提取 三 代码实现 打赏 在CBIR中 图像通过其视觉内容 例如颜色 纹理 形状 来索引 一 实现原理 首先从图像数据库中提取特征并存储它 然后我们计算与查询图像相关的特征 最后 我们检索
  • use MinGW compile googletest on windows

    table of contents enviornments brief description of software installation MinGW installation cmake installation googlete
  • word文档墨迹工具的笔不能用_CourseMaker微课制作教程43:手写设备在Word、PPT、PDF里的使用方法大全...

    首先我们要有个概念 手写设备 数位板 纸笔手写板 数位屏 在各个软件里能否书写 跟这些设备硬件本身并没有什么关系 不是说这个牌子的手写板在A软件里能用 那个牌子的手写板在A软件里不能用 能否在软件里手写 主要还是看软件里的手写功能组件是否完
  • linux驱动12:主设备号和次设备号

    dev目录下执行ls l 设备文件项的最后修改日期前的用逗号分割的两个数 对设备文件来说就是相应的主设备号和次设备号 第一个字符c表示字符设备 b表示块设备 主设备号标识设备对应的驱动程序 次设备号由内核使用 用于正确确定设备文件所指的设备
  • [答疑]《软件方法》自测题为什么不直接给出答案?

    软件方法 下 分析和设计第8章连载 20210518更新 gt gt 问题 很多同学说 软件方法 各章的自测题要扫码到全对才知道答案 比较费劲 能不能直接给出答案 统一回答如下 这是有意为之的 这些题是多年积累下来 围绕着书中的知识点精心准
  • 普通光照模型:unityshader

    我们都知道物体表面的光照是由 自发光 镜面光 高光 环境光 漫反射得出来的 环境光 光照系数 环境光颜色 Ambient K GlobalAmbient 漫反射 Diffuse K LightColor max dot N L 0 反射光线
  • 【linux系统安装nvm】

    linux系统安装nvm 直接用脚本一键安装 sudo apt install curl curl https raw githubusercontent com creationix nvm master install sh bash
  • React Antd HelloWorld

    react antdesign helloworld 安装antd 第一个示例HelloWorld 报错解决 快速解决 安装antd 使用 npm 或 yarn 安装 我们推荐使用 npm 或 yarn 的方式进行开发 不仅可在开发环境轻松
  • visio 2010激活教程

    一 下载office2010toolkit zip 若下载链接失效 手动搜索office2010toolkit http ys c ys168 com 605279628 o4W138W45JIPI5SiuWf5 office2010too
  • NLP 做词频矩阵时,遇到特大矩阵触发memoryerror的处理方式

    昨天做NLP词频矩阵处理时候 遇到内存不足的问题 遇到memoryerror的情况 查了不少资料 都让我在大的机器上跑 但是有时候资源有限 由于我的句子中的每个词语都是重要的 所以不设置停用词 也就是countvectoirze才符合我的需
  • ffmpeg--使用命令+EasyDarwin推流笔记本摄像头

    手头没有网络摄像头 采用ffmpeg EasyDarwin 笔记本摄像头模拟一个网络摄像头用来开发程序 有一些小细节记录一下 EasyDarwin安装使用 流媒体服务器easydarwin的安装还是非常方便的 参考官方给的readme 几分
  • 三层架构实现增删改查操作封装

    文章目录 概要 整体架构流程 技术名词解释 技术细节 小结 概要 三层架构 三层架构分为 数据 dao 层 业务 service 层 控制 controller 层 1 表示层 USL 即User Show Layer 视图层 a 前台 对