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

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  1. 书写Service
package com.bz.service;

public interface UserService {
    /\*\*
 \* 用户登录
 \* @param username 用户输入的账号名
 \* @param pwd 用户输入的密码
 \* @return 是否登录成功
 \*/
    boolean login(String username,String pwd) throws Exception;
}

  1. 书写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;
        }
    }
}


  1. 书写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

* **必须测试**
  1. 搭建Service

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

[外链图片转存中…(img-DHPzXYWX-1715636686238)]
[外链图片转存中…(img-0tO8ON4g-1715636686239)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值