高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤

这篇具有很好参考价值的文章主要介绍了高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✅作者简介:热爱后端语言的大学生,CSDN内容合伙人
✨精品专栏:C++面向对象
🔥系列专栏:JDBC快速入门

1、三层架构

  • 一种合理的项目分层理念,好处为可以简化设计、各司其职、更容易扩展内容
  • 三层架构分为:
    • 表示层(UI、WEB):跟用户对接
    • 业务逻辑层(service):书写功能的整体逻辑
    • 数据访问层(dao):对接数据库

1.1、数据访问层

  • DAO:和数据库交接、内存放着对数据库内容增删改查的方法

1.2、业务逻辑层

  • Service:存放着代表主要功能的方法,内部内容主要为调用DAO+逻辑控制代码

1.2.1、组成

Service接口:

  1. 一张表对应一个Service
  2. Service中存放着与该表相关的所有功能方法
  3. 命名与表名相关:PersonService
  4. 包:须存放在service包下 com.xxx.service

Service实现类:

  1. 一个实现类实现一个service接口
  2. 命名为接口名+Impl:PersonServiceImpl
  3. 包:须存放在service.impl下 com.xxx.service.impl

1.3、表示层

  • view:负责跟用户对接

1.3.1、实现

  1. 一个功能一个视图类
  2. 命名:功能+View
  3. 包:须放在view包下 com.xxx.view
  4. 内容:调用service+Scanner

1.4、完整实现步骤

  1. 书写实体类

    package com.bz.entity;
    
    import java.io.Serializable;
    
    public class User implements Serializable {
        private Integer id;
        private String username;
        private String pwd;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    
        public User(Integer id, String username, String pwd) {
            this.id = id;
            this.username = username;
            this.pwd = pwd;
        }
    }
    
  2. 书写DAO

    package com.bz.dao;
    
    import com.bz.entity.User;
    
    /**
     * 跟数据库对接:从数据库中查找user信息
     */
    public interface UserDao {
        /**
         * 查询用户信息是否存在
         * @param username  用户名
         * @param pwd 密码
         * @return  用户对象
         */
        User selectUser(String username,String pwd) throws Exception;
    }
    
    
  3. 书写DaoImpl

    package com.bz.dao.impl;
    
    import com.bz.dao.UserDao;
    import com.bz.entity.User;
    import com.bz.util.JDBCUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public User selectUser(String username, String pwd) throws Exception {
            User user=null;//用来返回
    
            Connection conn= JDBCUtils.getConnection();
            String sql = "select * from t_user where u_username=? and u_pwd=?";
            PreparedStatement ps=conn.prepareStatement(sql);
            ps.setString(1,username);
            ps.setString(2, pwd);
    
            ResultSet rs=ps.executeQuery();
            if (rs.next()) {
                Integer id = rs.getInt("u_id");
                String name = rs.getString("u_username");
                String password = rs.getString("u_pwd");
                user = new User(id, name, password);
            }
    
            JDBCUtils.close(rs,ps,conn);
    
            return user;
        }
    }
    
    
  4. 书写Service

    package com.bz.service;
    
    public interface UserService {
        /**
         * 用户登录
         * @param username  用户输入的账号名
         * @param pwd 用户输入的密码
         * @return 是否登录成功
         */
        boolean login(String username,String pwd) throws Exception;
    }
    
  5. 书写ServiceImpl

    package com.bz.service.impl;
    
    import com.bz.dao.UserDao;
    import com.bz.dao.impl.UserDaoImpl;
    import com.bz.service.UserService;
    
    public class UserServiceImpl implements UserService {
        //创建Dao对象
        private UserDao ud=new UserDaoImpl();
    
        @Override
        public boolean login(String username, String pwd)throws Exception {
            if (ud.selectUser(username, pwd)!=null) {
                return true;
            }else{
                return false;
            }
        }
    }
    
    
  6. 书写view

    package com.bz.view;
    
    import com.bz.service.UserService;
    import com.bz.service.impl.UserServiceImpl;
    
    import java.util.Scanner;
    
    /**
     * 用户登录
     */
    public class UserloginTest {
        public static void main(String[] args) throws Exception{
    
            UserService us=new UserServiceImpl();
    
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username=sc.next();
            System.out.println("请输入密码:");
            String pwd=sc.next();
    
            //调用Service方法判断登录是否成功
            if (us.login(username,pwd)){
                System.out.println("登录成功!");
            }else {
                System.out.println("登录失败");
            }
    
    
        }
    }
    
    

2、事务及JDBCUtils最终版

  • 回顾事务概念:将多个操作步骤归为同一个原子操作,要么同时成功,要么同时失败

    开启事务

    执行操作

    结束事务:commit rollback

  • 通常需要添加在Service层,Service层的所有功能方法都应该配套事务

2.1、事务基本操作与问题解决

  1. 开启事务:Connection对象.setAutoCommit(false)
  2. 结束事务:
    • 提交:Connection对象.commit();
    • 回滚:Connection对象.rollback();

2.1.1、存在问题

操作事务和操作数据库数据的数据库连接不是同一个,或导致事务回滚不会影响数据库内容

2.1.2、解决方案:ThreadLocal

  • 思路: 放入线程的存储空间中,ServiceDAO不再自行创建conn,如有需要,直接从线程存储空间中取出

  • 实现:

    1. 确保工具类只会创建一个conn对象

    2. 使用ThreadLocal将工具类创建的conn对象放入存储空间

      ThreadLocal:可以操作线程存储空间的工具,可以对空间的数据进行添加、获取、删除

      添加:ThreadLocal对象.set(数据)

      获取:ThreadLocal对象.get()

      删除:ThreadLocal对象.remove()

  • 使用:

    • 由于DAO和Service共用同一个conn,并且Service一定晚于DAO执行结束,所以为了确保Service的执行,DAO中不能关闭conn,该操作应由Service完成

2.2、JDBCUtils-最终版

package com.bz.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * 工具类:方便方法调用,所有方法都应为静态方法
 */
public class JDBCUtils {
    //提升集合的作用范围,确保getConnection方法中也能使用
    private static Properties p=null;
    //创建操作线程存储空间的工具对象
    private static ThreadLocal<Connection> tl=new ThreadLocal<>();

    //把流对象的创建放入静态初始代码块,确保在工具类类加载时执行
    static{
        try(
                //通过类对象.getResourseAsStream()获取一个字节输入流对象
                //当前配置文件在src之下
                InputStream is=JDBCUtils.class.getResourceAsStream("/jdbc.properties");
        ){
            //创建用来接收的Properties集合
            p=new Properties();
            //调用方法加载配置文件的内容至集合中
            p.load(is);
            //1. 加载驱动
            Class.forName(p.getProperty("driverClassName"));
        }catch (ClassNotFoundException e) {
            System.out.println("驱动路径不正确");
        } catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 获取Connection连接
     * @return
     */
    public static Connection getConnection(){
        Connection conn =tl.get();
        try {
            if (conn==null) {//这里如果线程存储空间里没有conn就创建conn并存入线程空间
                //2. 获取连接
                //连接的url
                String url = p.getProperty("url");
                //用户名
                String username = p.getProperty("username");
                //密码
                String pwd = p.getProperty("password");
                conn = DriverManager.getConnection(url, username, pwd);
                //将新创建的conn放入线程的存储空间
                tl.set(conn);
            }
        } catch (SQLException e) {
            System.out.println("获取连接失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }
        return conn;
    }
    /**
     * 关闭资源连接  非空判断:防止空指针
     * @param rs
     * @param ps
     * @param conn
     */
    public static void close(ResultSet rs, PreparedStatement ps,Connection conn){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                System.out.println("关闭rs失败");
            }
        }
        if (ps!=null){
            try {
                ps.close();
            } catch (SQLException e) {
                System.out.println("关闭ps失败");
            }
        }
        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                System.out.println("关闭conn失败");
            }
        }
    }
}

3、JUnit测试框架

  • 作用:DAO层和Service层中的方法通常需要经过测试JUnit可以通过@Test注解完成执行测试,大大减少测试成本

3.1、使用步骤

  1. 导入jar包:

    • hamcrest-core-1.3.jar

    • junit-4.12.jar

  2. 创建测试类

    • 命名:被测试的类/接口+Test
    • 包:须放在test包下
  3. 使用

    • @Test注解必须写在方法上方
    • 方法必须为公开、非静态、无参、无返回值的最普通的普通方法
    • 一个测试方法中只能测试一个方法
    • 通常情况下,测试方法名应与被测试方法一致,目的更为清晰

3.2、使用示例

package com.bz.test;

import com.bz.dao.AccountDao;
import com.bz.dao.impl.AccountDaoImpl;
import com.bz.entity.Account;
import org.junit.Test;

public class AccountDaoImplTest {

    //创建被测试的对象
    AccountDao ad=new AccountDaoImpl();

    @Test
    public void selectAccountByName(){
        Account a = ad.selectAccountByName("张三");
        System.out.println(a);
    }
    @Test
    public void updateAccountByName(){
        int n = ad.updateAccountByName("张三", 100);
        System.out.println(n);
    }
}

4、JDBC项目开发步骤总结

首先要根据要求来建库建表(数据库的内部操作)

  1. 导入jar包:

    hamcrest-core-1.3.jar
    junit-4.12.jar
    mysql-connector-java-8.0.23.jar

  2. 添加工具类(JDBCUtils最终版)

  3. 在src下添加工具类所需的jdbc.properties

  4. 书写实体类

  5. 搭建DAO

    • 必须测试
  6. 搭建Service

    • 最好也进行测试
  7. 书写view(不需要过多关注,实际开发中该层对接的应该是浏览器页面

项目结构图示:

高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤,# JDBC,junit,架构,数据库,java


高效掌握JDBC的分享到此结束,希望对大家有所帮助,如有疑问欢迎大家交流指正。文章来源地址https://www.toymoban.com/news/detail-599750.html

到了这里,关于高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【开篇 | Spring深度学习】Spring设计理念和整体架构

    个人名片: 🐼 作者简介:一名大二在校生 🐻‍❄️ 个人主页:落798. 🐼 个人WeChat:落798. 🕊️ 系列专栏: 零基础学java ----- 重识c语言 ---- 计算机网络 — 【Spring技术内幕】 🐓 每日一句: 努力赚钱,娶她回家! Spring 是最流行的企业 Java 应用程序开发框架。 全球数以百

    2024年02月16日
    浏览(50)
  • 【手撕Spring - 深入篇】Spring 的设计理念和整体架构

    👉 博主介绍 : 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区:个人社区 💞 个人主页:个人主页 🙉 专栏地址: ✅ 带你手撕 Spring 🙉八股文专题:剑指大厂,

    2024年02月14日
    浏览(43)
  • [React源码解析] React的设计理念和源码架构 (一)

    任务分割 异步执行 让出执法权 1.React的设计理念 Fiber: 即对应真实dom, 又作为分隔单元。 Scheduler: 用js实现一套时间片运行的机制, 使得requestIdleCallback()的浏览器的兼容性和触发不稳定的问题解决。 Lane: 异步调度有了, 需要细粒度的管理各个任务的优先级, 让高优先级的先执行

    2024年02月07日
    浏览(39)
  • 深入学习SpringCloud Alibaba微服务架构,揭秘Nacos、Sentinel、Seata等核心技术,助力构建高效系统!

    链接: https://pan.baidu.com/s/1hRN0R8VFcwjyCTWCEsz-8Q?pwd=j6ej 提取码: j6ej 复制这段内容后打开百度网盘手机App,操作更方便哦 --来自百度网盘超级会员v4的分享 📚【第01阶段】课程简介:全面介绍课程内容,为你提供学习引导和目标规划,让你快速进入学习状态!💡 🔍【第02阶段】基

    2024年02月12日
    浏览(55)
  • 《移动互联网技术》 第十章 系统与通信: 掌握Android系统的分层架构设计思想和基于组件的设计模式

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月16日
    浏览(56)
  • 从零开始理解Linux中断架构(2)-朴素的中断管理设计理念

            既然是从零开始,我们先从最为简单的中断逻辑处理架构开始,这个逻辑结构跟CPU架构没有关系,纯逻辑上的。纯逻辑是跨越系统和应用的,不管对于应用程序员还是系统程序员,逻辑推导是基本的工具,设计原型是基本的出发点。         在系统初始化的时

    2024年02月08日
    浏览(43)
  • Web应用三层架构和Java后端(应用层)三层架构

    Web应用三层架构(对于整个项目应用而言) 1.客户端层UI层:主要用来与用户进行交互,显示数据并接收用户的输入,也常称为前端。一般对于一个应用通常会存在多种客户端(前端),如Web,H5,App等。 2.应用层:是系统核心价值部分,其关注业务规则的制定和业务流程的实现

    2024年02月16日
    浏览(43)
  • 系统架构:经典三层架构

    经典三层架构是分层架构中最原始最典型的分层模式,其他分层架构都是其变种或扩展,例如阿里的四层架构模式和DDD领域驱动模型。阿里的 四层架构模型在三层基础上增加了 Manager 层,从而形成变种四层模型;DDD架构则在顶层用户界面层与业务逻辑层之间引入应用层,从而

    2024年02月03日
    浏览(37)
  • 三层架构与MVC架构区别

    表示层:主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。 servlet层 业务逻辑层:对我们数据实现业务逻辑的封装 service层 数据访问层:对数据库访问操作 dao层         1.MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写

    2024年02月04日
    浏览(44)
  • MVC三层架构

    1.MVC三层架构 MVC(Model-View-Controller)是一种常见的软件设计模式,用于组织和管理应用程序的代码和逻辑。它将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。每个部分都有不同的职责和功能,以实现代码的分离和可维护性。 下面是对MVC三层

    2024年02月15日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包