一个JDBC访问oracle数据库表的例子,让你搞清三层架构与MVC框架模式之间的关系,以及满足设计原则的类的结构和各类的职责

Posted Java Old Man

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个JDBC访问oracle数据库表的例子,让你搞清三层架构与MVC框架模式之间的关系,以及满足设计原则的类的结构和各类的职责相关的知识,希望对你有一定的参考价值。

问题描述

我们以访问oracl数据库的emp表为例,来对java对数据库的访问相关问题进行一下详细讨论。
我们需要完成的功能是可以通过命令控制台以及键盘输入,来实现对emp表的增,删,查,改等功能。
这里不讨论通过任何框架来实现数据库的访问,比如mybatis等。
但会考虑三层架构等设计问题。

类的设计

三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体。


从上图我们可以分析出,所需要的类有:

实体层(entity)

Emp类

Emp类,属业务实体类,因考虑到方便,实体类的名称与表的名称相一致。其属性与表中的字段一一对应,并有各属性的setter和getter方法。
所有实体类放在com.javaoldman.entity包中。

  • emp表结构
名称    是否为空? 类型
------- -------- ----------
EMPNO   NOT NULL NUMBER(4)
ENAME            VARCHAR2(10)
JOB              VARCHAR2(9)
MGR              NUMBER(4)
SAL              NUMBER(7,2)
COMM             NUMBER(7,2)
DEPTNO           NUMBER(2)
  • Emp类的定义
package com.javaoldman.entity;

public class Emp 
  private int empno;
  private String ename;
  private String job;
  private int mgr;
  private double sal;
  private double comm;
  private int deptno;

  public int getEmpno() 
    return empno;
  

  public String getEname() 
    return ename;
  

  public String getJob() 
    return job;
  

  public int getMgr() 
    return mgr;
  

  public double getSal() 
    return sal;
  

  public double getComm() 
    return comm;
  

  public int getDeptno() 
    return deptno;
  

  public void setEmpno(int empno) 
    this.empno = empno;
  

  public void setEname(String ename) 
    this.ename = ename;
  

  public void setJob(String job) 
    this.job = job;
  

  public void setMgr(int mgr) 
    this.mgr = mgr;
  

  public void setSal(double sal) 
    this.sal = sal;
  

  public void setComm(double comm) 
    this.comm = comm;
  

  public void setDeptno(int deptno) 
    this.deptno = deptno;
  

  @Override
  public String toString() 
    return "Emp" +
            "empno=" + empno +
            ", ename='" + ename + '\\'' +
            ", job='" + job + '\\'' +
            ", mgr=" + mgr +
            ", sal=" + sal +
            ", comm=" + comm +
            ", deptno=" + deptno +
            '';
  

数据访问层(DAO)

数据访问层实现对于数据库的具体操作,包括增删改查等。
但考虑到可能会连接不同的数据库类型,所以, 为了解除业务逻辑层与DAO层的耦合,将DAO层进行符合依赖倒置原则的设计。即分成DAO接口和DAO具体实现类两层。

同理,为了解除表示层对业务逻辑层的依赖,也将业务逻辑层分成接口和实现类两层。

EmpDao 接口

EmpDao接口,定义数据访问的方法。主要方法有:

  • 查询所有emp记录
  • 按empno查询emp记录
  • 按empno删除emp记录
  • 添加新的emp记录
  • 按empno来更新emp记录
    所有dao接口放在com.javaoldman.dao包内。

EmpDao代码:

package com.javaoldman.dao;

import com.javaoldman.entity.Emp;

import java.util.List;

public interface EmpDao 
    List<Emp> selectAllEmp();
    Emp selectEmpByEmpno(int empno);
    int deleteEmpByEmpno(int empno);
    int insertEmp(Emp emp);
    int updateEmp(Emp emp);

从接口方法的申明中可以看出,方法的入口参数以及返回值多是为Emp对象或集合,这也是将关系数据库中的表记录与实体对象进行映射的关键。这可以让业务逻辑层只面向对象,不需要面向数据库的细节。

JDBCUtil工具类

因为访问数据库,有许多的代码是重复的,包括数据库的驱动注册,连接对象等,还有数据库访问结束后的资源释放等。所以,可能定义一个工具类,来实现这些重复性的工作。比如直接获得一个连接对象,或直接释放数据库资源等。
这个类可以放在com.javaoldman.util包中
代码如下:

package com.javaoldman.util;

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

/**
 * JDBC工具类
 */
public class JDBCUtil 
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    //静态代码块,在程序编译的时候执行
    static 
        try 
            //创建Properties对象
            Properties p = new Properties();
            //获取文件输入流
            InputStream in = JDBCUtil.class.getResourceAsStream("/db.properties");
            //加载输入流
            p.load(in);
            //获取数据库连接驱动名字
            driver = p.getProperty("driver",null);
            //获取数据库连接地址
            url = p.getProperty("url",null);
            //获取数据库连接用户名
            username = p.getProperty("username",null);
            //获取数据库连接密码
            password = p.getProperty("password",null);
            if(driver != null && url != null
                    && username != null && password != null)
                //加载驱动
                Class.forName(driver);
            
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     * 获取连接对象
     * @return Connection连接对象
     */
    public static Connection getConn()
        Connection conn = null;
        try 
            conn = DriverManager.getConnection(url,username,password);
         catch (SQLException e) 
            e.printStackTrace();
        
        return conn;
    

    /**
     * 关闭连接(Connection连接对象必须在最后关闭)
     * @param conn Connection连接对象
     * @param st 编译执行对象
     * @param rs 结果集
     */
    public static void close(Connection conn, Statement st, ResultSet rs)
        try 
            if(rs != null)
                rs.close();
            
            if(st != null)
                st.close();
            
            if(conn != null)
                conn.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
    

属性文件

数据库连接需要一些属性数据,比如URL,用户名,密码,还有驱动的类名等,为了让修改,可以将这些信息保存在一个属性文件中,方便修改。在工具类中,读取这个属性文件来设置相关的值。
在项目目录中创建一个properties的属性文件db.properties,里面定义了四行数据,分别对应着JDBC连接所需要的几个参数(注:Properties底层为一个Hashtable,配置文件中“=”之前的代表Map中的键,之后的代表相应键所对应的值)

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger

EmpDaoImpl实现类

EmpDaoImpl是对EmpDao接口的具体实现,分别实现接口中的所有方法。在该类中,实现具体的通过JDBC访问ORACLE数据库的相关操作。
该类放在com.javaoldman.dao.impl包中。
代码:

package com.javaoldman.dao.impl;

import com.javaoldman.dao.EmpDao;
import com.javaoldman.entity.Emp;
import com.javaoldman.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 EmpDaoImpl implements EmpDao 

    @Override
    public List<Emp> selectAllEmp() 
        Connection connection = JDBCUtil.getConn(); //通过工具类直接得到Connection对象
        String sql = "select * from emp";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Emp> empList = new ArrayList<>();
        try 
             preparedStatement = connection.prepareStatement(sql);
             resultSet = preparedStatement.executeQuery();
             while (resultSet.next())
                 Emp emp = new Emp();
                 emp.setEmpno(resultSet.getInt("empno"));
                 emp.setEname(resultSet.getString("ename"));
                 emp.setJob(resultSet.getString("job"));
                 emp.setMgr(resultSet.getInt("mgr"));
                 emp.setSal(resultSet.getDouble("sal"));
                 emp.setComm(resultSet.getDouble("comm"));
                 emp.setDeptno(resultSet.getInt("deptno")); //组装emp对象
                 empList.add(emp); //组装emp集合
             
         catch (SQLException e) 
            e.printStackTrace();
        finally 
            JDBCUtil.close(connection,preparedStatement,resultSet); //释放数据库资源
        
        return empList;  //返回emp集合
    

    @Override
    public Emp selectEmpByEmpno(int empno) 
        Connection connection = JDBCUtil.getConn(); //通过工具类直接得到Connection对象
        String sql = "select * from emp where empno = ?";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Emp> empList = new ArrayList<>();
        Emp emp = null;
        try 
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,empno);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next())
                emp = new Emp();
                emp.setEmpno(resultSet.getInt("empno"));
                emp.setEname(resultSet.getString("ename"));
                emp.setJob(resultSet.getString("job"));
                emp.setMgr(resultSet.getInt("mgr"));
                emp.setSal(resultSet.getDouble("sal"));
                emp.setComm(resultSet.getDouble("comm"));
                emp.setDeptno(resultSet.getInt("deptno")); //组装emp对象
            
         catch (SQLException e) 
            e.printStackTrace();
        finally 
            JDBCUtil.close(connection,preparedStatement,resultSet); //释放数据库资源
        
        return emp;  //如果有记录,就返回emp,否则返回null
    

    @Override
    public int deleteEmpByEmpno(int empno) 
        Connection connection = JDBCUtil.getConn(); //通过工具类直接得到Connection对象
        String sql = "delete from emp where empno = ?";
        PreparedStatement preparedStatement = null;
        int num = 0;
        try 
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,empno);
            num = preparedStatement.executeUpdate();
         catch (SQLException e) 
            e.printStackTrace();
        finally 
            JDBCUtil.close(connection,preparedStatement,null); //释放数据库资源,因为没有记录集对象,所以,用null
        
        return num;  //返回受影响的行数
    

    @Override
    public int insertEmp(Emp emp) 
        Connection connection = JDBCUtil.getConn(); //通过工具类直接得到Connection对象
        int empno;
        String ename;
        String job;
        int mgr;
        double sal;
        double comm;
        int deptno;

        empno = emp.getEmpno();
        ename = emp.getEname();
        job = emp.getJob();
        mgr = emp.getMgr();
        sal = emp.getSal();
        comm = emp.getComm();
        deptno = emp.getDeptno();

        String sql = "insert into emp(empno,ename,job,mgr,sal,comm,deptno) values(?,?,?,?,?,?,?)";
        PreparedStatement preparedStatement = null;
        int num = 0;
        try 
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,empno);
            preparedStatement.setString(2,ename);
            preparedStatement.setString(3,job);
            preparedStatement.setInt(4,mgr);
            preparedStatement.setDouble(5,sal);
            preparedStatement.setDouble(6,comm);
            preparedStatement.setInt(7,deptno);

            num = preparedStatement.executeUpdate();
         catch (SQLException e) 
            e.printStackTrace();
        finally 
            JDBCUtil.close(connection,preparedStatement,null); //释放数据库资源,因为没有记录集对象,所以,用null
        
        return num;  //返回受影响的行数
    

    @Override
    public int updateEmp(Emp emp) 
        Connection connection = JDBCUtil.getConn(); //通过工具类直接得到Connection对象
        int empno;
        String ename;
        String job;
        int mgr;
        double sal;
        double comm;
        int deptno;

        empno = emp.getEmpno();
        ename = emp.getEname();
        job = emp.getJob();
        mgr = emp.getMgr以上是关于一个JDBC访问oracle数据库表的例子,让你搞清三层架构与MVC框架模式之间的关系,以及满足设计原则的类的结构和各类的职责的主要内容,如果未能解决你的问题,请参考以下文章

oracle表的crud(增删改查)单表

就是要让你搞懂Nginx,这篇就够了!

oracle左连接查询和右连接查询随便举个例子谢谢!

让你搞懂如何通过Nginx来解决跨域问题

一文让你搞懂Spring的统一事务模型

3分钟让你搞懂交换机接口数据处理过程