JDBC三层架构

三层架构

三层架构是一种软件设计结构 ,是一种组织代码的手段和方式,在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。推荐的分层式结构一般分为三层,从上至下分别为:表示层、业务逻辑层(又或称为领域层)、持久层
区分层次的目的是为了高内聚低耦合的思想。

通常意义上就是将整个业务应用划分为:
表示层:数据的显示或者录入
业务逻辑层:业务的具体操作流程
持久层:操作数据库,针对数据库表CRUD(增删改查)

三层架构的实现
dao:持久层
entity:实体类
service:业务层
utils:工具类
view:表示层

要以三层架构来实现一个业务,我们要从几个方面入手,按先后顺序来区分:
​ 1、分析需求

​ 2、拆解业务逻辑

​ 3、确定调用关系

​ 4、定义接口

以登录业务为例:
业务需求:用户输入用户名和密码,检查,正确就登录,错误给出提示信息

表示层:
采集用户输入,显示错误信息
输入:String用户名,String密码,
输出:user对象(包含username和password属性)
显示错误信息(输入:login对象,输出:String login.errorInfo值)

业务逻辑层:检查用户的用户名和密码,判断是否允许登录
校验用户密码,判断是否允许登录
​ 输入:login对象,输出:boolean
持久层:查询用户名和用户密码
查询用户密码
​ 输入:user对象,
​ 输出:String username, String password)
如果没查到用户,返回null,否则返回数据库中保存的密码。

​ 判断是否允许登录
​ 输入:login对象,输出:boolean

实现实体类

实体类
属性一般用private修饰,getter/setter方法,重写tostring等可使用Lombok及相应架包来大大减少代码量,仅需@Data就可以完成完成。
对实体类提供无参构造方法,根据业务需要提供相应的有参构造方法,可以利用lombok的@AllArgsConstructoh和@NoArgsConstructor来提供分别提供有参构造方法和无参构造方法;
接口类

​ 接口类的定义要根据业务需求,在逻辑层的调用需求,都需要在接口层定义相应的接口。
​ 只要是实现了此接口的实现类,都可以在逻辑层被正常调用,这样就实现了底层实现类更新扩展替换,而不影响到逻辑层代码的目的。

接口的实现类

​ 接口的实现类具体实现接口逻辑,根据底层存储的不同,可以有多种不同的实现类,每个实现类对应一种底层存储。

数据库操作工具类
    将通用操作(数据库打开连接,关闭连接)封装到工具类中,避免数据库连接和关闭代码的重复使用,方便修改。
public class  DButils{
    private String driver = "com.mysql.cj.jdbc.Driver";// 数据库驱动字符串,MySQL版本为8,mysql5的去掉cj即可
	private String url = "jdbc:mysql://localhost:3306/jdbc";// 连接URL字符串
	private String user = "root"; // 数据库用户名
	private String password = "root"; // 用户密码
    Connection conn = null;				// 数据连接对象
    /**
     * 获取数据库连接对象
     */
    public Connection getConnection() {
        if(conn==null) {
            // 获取连接并捕获异常
            try {
                Class.forName(driver);
                conn = DriverManager.getConnection(url, user, password);
            } catch (Exception e) {
                e.printStackTrace();				// 异常处理
            }
        }
        return conn;							// 返回连接对象
    }
    /**
     * 关闭数据库连接
     * @param conn 数据库连接
     * @param stmt Statement对象
     * @param rs 结果集
     */
    public void closeAll(Connection conn, Statement stmt, ResultSet rs) {
        // 若结果集对象不为空,则关闭
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 若Statement对象不为空,则关闭
        if (stmt != null) {
            try {
                stmt.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 若数据库连接对象不为空,则关闭
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

​实现通用的增删改操作(采用预处理SQL模式 )。

 /**
	 * 增、删、改的操作
	 * @param sql 预编译的 SQL 语句          
	 * @param param 参数的字符串数组          
	 * @return 影响的行数
	 */
	public int exceuteUpdate (String preparedSql, Object[] param) {
		PreparedStatement pstmt = null;
		int num = 0;
		conn =  getConnection(); 
		try {
			pstmt = conn.prepareStatement(preparedSql);
			if (param != null) {
				for (int i = 0; i < param.length; i++) {
                     	//为预编译sql设置参数
					pstmt.setObject(i + 1, param[i]); 
				}
			}
			num = pstmt.executeUpdate(); 
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			closeAll(conn,pstmt,null);
		}
		return num;
	}

其他部分,根据业务具体需求去实现

Lombok

可以帮我们省略setter/getter,tostring这些代码

使用步骤

1、安装Lombok插件
File—Settings—Plugins,搜索Lombok

在这里插入图片描述

2、导包
lombok-1.18.24.jar
3、使用
package com.blb.demo3.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * EmployeeId Varchar(20) 员工帐号 
 * Password Varchar(20) 登录密码 
 * EmployeeName Varchar(50) 姓名 
 * Age Int 年龄 
 * Salary Decimal(12,3) 工资
 */
@Data					//提供set、get,toString方法
@AllArgsConstructor		//提供有参构造方法
@NoArgsConstructor		//提供无参构造方法
public class ErpEmployee {
    private String EmployeeId;
    private String Password;
    private String EmployeeName;
    private int Age;
    private double Salary;
}

Java连接池

当我们创建了一个Connection对象,它在内部都执行了什么:

​ 1.“DriverManager”检查并注册驱动程序;

​ 2.“com.mysql.jdbc.Driver”就是我们注册了的驱动程序,它会在驱动程序类中调用“connect(url…)”方法。

​ 3.com.mysql.jdbc.Driver的connect方法根据我们请求的“connUrl”,创建一个“Socket连接”,连接到IP为“your.database.domain”,默认端口3306的数据库。

​ 4.创建的Socket连接将被用来查询我们指定的数据库,并最终让程序返回得到一个结果。

​ 简单的获取一个连接,系统却要在背后做很多消耗资源的事情,大多时候,创建连接的时间比执行sql语句的时间还要长。

为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。

原理:
​ 先打开一定数量的数据库连接,当使用的时候分配给调用者,调用完毕后返回给连接池,注意返回给连接池后这些连接并不会关闭,而是准备给下一个调用者进行分配。由此可以看出连接池节省了大量的数据库连接打开和关闭的动作,对系统性能会有较大地提升。

Spring—JDBC

一个由Spring团队开发的JDBC工具类,作用和DBUtils相同,目前作为代替DBUtils的工具

使用步骤:
1.导包
spring-beans-5.3.22.jar
spring-core-5.3.22.jar
spring-jcl-5.3.22.jar
spring-jdbc-5.3.22.jar
spring-tx-5.3.22.jar

2.创建JdbcTemplate工具

package com.blb.utils;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.io.IOException;
import java.util.Properties;

public class JdbcTemplateUtils {

    private static HikariDataSource hikariDataSource;
    private static JdbcTemplate jdbcTemplate;
    private static DataSourceTransactionManager transactionManager;
    private static DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();

    static{
        try {
            Properties properties = new Properties();
            properties.load(JdbcTemplateUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            HikariConfig hikariConfig = new HikariConfig(properties);
            hikariDataSource = new HikariDataSource(hikariConfig);
            transactionManager = new DataSourceTransactionManager(hikariDataSource);
        } catch (IOException e) {
            System.out.println("配置文件找不到,使用默认配置");
        }
    }

    /**
     * 获取JdbcTemplate
     * @return
     */
    public static JdbcTemplate getJdbcTemplate(){
        if (jdbcTemplate==null) {
            jdbcTemplate = new JdbcTemplate(hikariDataSource);
        }
        return jdbcTemplate;
    }

    /**
     * 开启事务
     * @return
     */
    public static TransactionStatus beginTransaction(){
        return transactionManager.getTransaction(transactionDefinition);
    }

    /**
     * 开启事务
     * @param transactionDefinition
     * @return
     */
    public static TransactionStatus beginTransaction(TransactionDefinition transactionDefinition){
        return transactionManager.getTransaction(transactionDefinition);
    }

    /**
     * 提交事务
     * @param transactionStatus
     */
    public static void commit(TransactionStatus transactionStatus){
        transactionManager.commit(transactionStatus);
    }

    /**
     * 回滚事务
     * @param transactionStatus
     */
    public static void rollback(TransactionStatus transactionStatus){
        transactionManager.rollback(transactionStatus);
    }
}

3.使用JdbcTemplate完成CRUD操作

package com.blb.demo3.dao.impl;

import com.blb.demo3.dao.IEmployeeDao;
import com.blb.demo3.entity.ErpEmployee;
import com.blb.demo3.utils.JdbcTemplateUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class EmployeeDaoImpl implements IEmployeeDao {
    JdbcTemplate jdbcTemplate = JdbcTemplateUtils.getjdbcTemplate();

    /**
     * 新增
     * @param ev
     * @throws Exception
     */
    @Override
    public void create(ErpEmployee ev) throws Exception {
        jdbcTemplate.update("insert into erp_employee(EmployeeId, Password, EmployeeName, Age, Salary) values (?,?,?,?,?)",
                ev.getEmployeeId(), ev.getPassword(), ev.getEmployeeName(), ev.getAge(), ev.getSalary());
    }

    /**
     * 修改
     * @param ev
     * @throws Exception
     */
    @Override
    public void update(ErpEmployee ev) throws Exception {
        jdbcTemplate.update("update erp_employee set Password = ?, EmployeeName = ?, Age = ?, Salary = ? where EmployeeId = ?",
                ev.getPassword(), ev.getEmployeeName(), ev.getAge(), ev.getSalary(), ev.getEmployeeId());
    }

    /**
     * 删除
     * @param ev
     * @throws Exception
     */
    @Override
    public void delete(ErpEmployee ev) throws Exception {
        jdbcTemplate.update("delete from erp_employee where EmployeeId = ?");

    }


    /**
     * 查询
     * @return
     * @throws Exception
     */
    @Override
    public List<ErpEmployee> getAll() throws Exception {
        return  jdbcTemplate.query("select * from erp_employee",
                new BeanPropertyRowMapper<ErpEmployee>(ErpEmployee.class));
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值