10-10 分层模式/junit进行单元测试(必须掌握)/使用commons-dbutil简化jdbc

Dao模式

程序员写的是业务(因为其逻辑性不太强)

软件设计原则:开闭原则,对新增加的进行开放,对修改关闭

实际开发中, web项目, 程序员编写业务代码

把所有的代码都写在业务方法中:

  • 接收前端请求,获取请求参数...

  • 编写业务代码处理请求

  • 调用jdbc代码操作数据

  • 把数据进行加工

  • 把数据响应给前端

缺点:

  1. 方法很臃肿, 这个方法不便于复用, 部分重复代码重复写

  2. 方法的扩展性不好, 因为代码全部集中在一个方法内部, 替换某部分的代码,对这个方法进行修改

解决方案: 拆的思想

  1. 把方法拆分为多个方法, 不是OOP编程思想

  2. 把方法拆分为多个方法,把这个方法分类, 把不同功能的方法放在不同的类, 不同层次的类在进行分层(包)

常见的分层:

操作数据库的层: DAO层(数据访问层)

业务处理的层: service层(业务层)

表对应实体类层: 实体层(entity,pojo)

工具类存放的层: 工具层(util)

处理前端请求层: web层
分层的目的:

  1. 使用层来技术隔离, 方便每一层的技术替换,而不需要修改其他层

  2. 使用层来进行解耦, 每一层直接的调用, 以接口的形式

  1. 上下层之分, 上层调用下层,不能下层调用上层,不能跨层调用

使用dao模式开发:

  1. 编写实体类, 与数据库的表一一对应

    类与表对应

    一行记录对应类的一个对象

    表的字段对应类的属性

    数据库的数据类型与java的数据类型对应 java推荐使用包装类型

    mysql java
    int Integer/int
    bigint Long/long
    double Double/double
    decimal java.math.BigDecimal /Double
    char/varchar/text String
    date/datetime/time/timestamp java.util.Date
    tinyint Integer/int/Boolean
复制代码
、
package com.fs.soso.entity;
推荐使用
​
/**
 * 对应tb_card表的实体类
 */
public class Card {
   private Integer id;
   private String cardNumber;
   private Integer status;
​
   //get/set  toString
​
​
    public Integer getId() {
        return id;
    }
​
    public void setId(Integer id) {
        this.id = id;
    }
​
    public String getCardNumber() {
        return cardNumber;
    }
​
    public void setCardNumber(String cardNumber) {
        this.cardNumber = cardNumber;
    }
​
    public Integer getStatus() {
        return status;
    }
​
    public void setStatus(Integer status) {
        this.status = status;
    }
​
    @Override
    public String toString() {
        return "Card{" +
                "id=" + id +
                ", cardNumber='" + cardNumber + '\'' +
                ", status=" + status +
                '}';
    }
​
    public Card() {
    }
​
    public Card(Integer id, String cardNumber, Integer status) {
        this.id = id;
        this.cardNumber = cardNumber;
        this.status = status;
    }
​
    public Card(String cardNumber, Integer status) {
        this.cardNumber = cardNumber;
        this.status = status;
    }
}
​
  1. 编写dao接口,以及dao接口的实现类

    实体类--> 实体类dao接口 --> 实体类dao实现类--> 实体类业务接口 --> 实体类业务接口实现类

    Card --> [I]CardDao --> CardDaoImpl --> [I]CardService--> CardServiceImpl

    复制代码
    package com.fs.soso.dao;
    ​
    import com.fs.soso.entity.Card;
    ​
    import java.util.List;
    ​
    /**
     * 卡的数据访问接口
     * CURD
     */
    public interface CardDao {
        /**
         * 添加记录
         * @param card  手机卡对象
         * @return 受影响行数
         */
        int add(Card card);
    ​
        /**
         * 根据主键修改
         * @param card  手机卡对象
         * @return 受影响行数
         */
        int updateById(Card card);
    ​
        /**
         * 根据主键删除
         * @param id 主键值
         * @return 受影响行数
         */
        int deleteById(int id);
    ​
    ​
        /**
         * 根据主键查询
         * @param id 主键
         * @return 手机卡对象
         */
        Card queryById(int id);
    ​
    ​
        /**
         * 查询所有
         * @return 手机卡List集合
         */
        List<Card> queryAll();
    }
    ​
复制代码
package com.fs.soso.dao.impl;
​
import com.fs.soso.dao.CardDao;
import com.fs.soso.entity.Card;
import com.fs.soso.util.JdbcUtil;
​
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
​
public class CardDaoImpl implements CardDao {
    @Override
    public int add(Card card) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql ="insert into tb_card(cardNumber,status) values(?,?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setObject(1,card.getCardNumber());
            pstmt.setObject(2,card.getStatus());
            return pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtil.close(conn,pstmt,null);
        }
        return 0;
    }
​
    @Override
    public int updateById(Card card) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql ="update tb_card set status = ? where id = ? ";
            pstmt = conn.prepareStatement(sql);
            pstmt.setObject(1,card.getStatus());
            pstmt.setObject(2,card.getId());
            return pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtil.close(conn,pstmt,null);
        }
        return 0;
    }
​
    @Override
    public int deleteById(int id) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql ="delete from tb_card where id = ? ";
            pstmt = conn.prepareStatement(sql);
            pstmt.setObject(1,id);
            return pstmt.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtil.close(conn,pstmt,null);
        }
        return 0;
    }
​
    @Override
    public Card queryById(int id) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet resultSet = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql ="select * from  tb_card  where id = ? ";
            pstmt = conn.prepareStatement(sql);
            pstmt.setObject(1,id);
            resultSet = pstmt.executeQuery();
            Card card=null;
            while(resultSet.next()){
                card = new Card();
                //给属性赋值
                //getXxx(int 列的序号从1开始)
                //getXxx(String 列名)  可读性高
                card.setId(resultSet.getInt("id"));
                card.setCardNumber(resultSet.getString("cardNumber"));
                card.setStatus(resultSet.getInt("status"));
            }
            return card;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtil.close(conn,pstmt,null);
        }
        return null;
    }
​
    @Override
    public List<Card> queryAll() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet resultSet = null;
        try {
            conn = JdbcUtil.getConnection();
            String sql ="select * from  tb_card";
            pstmt = conn.prepareStatement(sql);
            resultSet = pstmt.executeQuery();
            List<Card> cards = new ArrayList<>();
            while(resultSet.next()){
                Card card = new Card();
                //给属性赋值
                card.setId(resultSet.getInt("id"));
                card.setCardNumber(resultSet.getString("cardNumber"));
                card.setStatus(resultSet.getInt("status"));
                //把对象添加到集合中
                cards.add(card);
            }
            return cards;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtil.close(conn,pstmt,null);
        }
        return null;
    }
}
​

junit进行单元测试(必须掌握)

对编写方法进行测试, 实际开发中,使用junit进行单元测试

使用步骤:

  1. 导入junit依赖

2.创建存放测试源代码的资源目录

项目完成之后, 删除测试代码

创建存放测试代码的资源目录 test

  1. 根据被测试的类(接口),生成对应的测试类

  1. 编写测试代码
复制代码
  package com.fs.soso.dao;
​
  import com.fs.soso.dao.impl.CardDaoImpl;
  import com.fs.soso.entity.Card;
  import org.junit.After;
  import org.junit.Before;
  import org.junit.Test;
​
  import static org.junit.Assert.*;
​
  public class CardDaoTest {
      private CardDao cardDao;
​
      /**
       * setUp() 使用 before修饰的, 表示该方法在调用测试方法之前执行
       * 做准备工作
       * @throws Exception
       */
      @Before
      public void setUp() throws Exception {
          //System.out.println("setUp...");
          cardDao = new CardDaoImpl();
      }
​
      /**
       * tearDown() 使用 After修饰的, 表示该方法在调用测试方法之后执行
       * 释放资源
       * @throws Exception
       */
      @After
      public void tearDown() throws Exception {
          //System.out.println("tearDown...");
      }
​
      /**
       *  @Test 标记方法上,表示这个方法是一个测试方法
       *    直接运行测试方法,不需要main调用
       *  测试方法要求:
       *   1. 返回值类型只能是void
       *   2. 一定是无参方法
       *   3.不能是static修饰
       */
      @Test
      public  void add() {
          //System.out.println("add...");
          Card card = new Card("16666666666",0);
          int rs =  cardDao.add(card);
          System.out.println(rs);
      }
​
      @Test
      public void updateById() {
          Card card = new Card(12,"16666666666",1);
          cardDao.updateById(card);
      }
​
      @Test
      public void deleteById() {
      }
​
      @Test
      public void queryById() {
          System.out.println(cardDao.queryById(12));
      }
​
      @Test
      public void queryAll() {
          System.out.println(cardDao.queryAll());
      }
  }

使用commons-dbutil简化jdbc

commons-dbutil是apache开源组织提供的封装jdbc的工具包

使用步骤:

  1. 导入commons-dbutil的jar
  1. 使用核心类, QueryRunner 执行增删改查的操作

结果集处理器:

  • BeanHandler: 把ResultSet转换为java实体对象

  • BeanListHandler: 把把ResultSet转换为List集合<java对象>

查询

增删改:

事务

jdbc的Connection默认是自动提交, 设置Connection为手动提交:

setAutoCommit(false); 手动提交

提交事务:

回滚事务:

事务概念: 面试重点

在同一个事务下,一组sql语句, 要就全部成功, 要就全部失败

事务的四大特征: ACID

嗖嗖移动大厅

1. 登录 业务流程

  1. 选择登录菜单

  2. 用户输入手机号码,密码

  3. 调用Dao层的方法,到数据库进行查询:

  4. 判断是否存在手机号码,密码记录, 如果存在, 判断是否被禁用

  5. 如果存在并且没有禁用, 登录成功, 显示二级菜单

  6. 否则,登录失败, 显示一级菜单

相关推荐
paopaokaka_luck4 分钟前
基于Spring Boot+Vue的多媒体素材管理系统的设计与实现
java·数据库·vue.js·spring boot·后端·算法
guoruijun_2012_411 分钟前
fastadmin多个表crud连表操作步骤
android·java·开发语言
Hello-Brand21 分钟前
Java核心知识体系10-线程管理
java·高并发·多线程·并发·多线程模型·线程管理
乐悠小码27 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.29 分钟前
Pod控制器
java·开发语言
2的n次方_31 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林55132 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.32 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七37 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
weisian15143 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全