JDBC高级面向对象实战技巧、封装增删改查操作、重构代码

  • 准备
  • 新建Maven工程、配置依赖
  • 代码
  • Orace增删改查原代码
  • 封装后的增删改查
  • 代码优化
  • 实现同时操作多个数据库


准备

这里用的Maven,idea,oracle。对于使用mysql的一样可以看这个,除了加载驱动的名称、url和少部分sql语句有区别,其他的操作可以说几乎一样。
文章较长,但一定要多敲代码

新建Maven工程、配置依赖

在创建一个maven项目,与之前的一致 JDBC的Maven项目创建 这里再添加个junit的依赖,用于测试代码。

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

完整的pom.xml是这样的

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.symc</groupId>
    <artifactId>jdbc-curd</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--    maven项目使用的jdk版本-->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--        引入oracle数据库依赖-->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.1.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>

别忘记修改编码和仓库位置,否则出现乱码问题和依赖代码报红。

点击转换,项目目录增加这些

数据库对象封装另一个对象unable to resolve 数据库对象_java

代码

Orace增删改查原代码

先练习一下最基础的,这个一定是要会写的,代码编译后,可以到数据库中查看一下。

这里@Test的注解,就是junit提供的,可以直接运行当前的方法。建议使用@Test注解的类写到test目录下。

package com.symc.example2;

import org.junit.Test;

import java.sql.*;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/09/29 18:31
 * @Description:
 */
public class Oracle_crud {

    @Test
    public void insert() throws ClassNotFoundException, SQLException {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl",
                "scott",
                "tiger");
        String sql = "insert into dept values(seq_1.nextval,?,?)";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1, "医学部");
        ps.setString(2, "沈阳");
        int i = ps.executeUpdate();
        if (i > 0) {
            System.out.println("成功插入[" + i + "]条数据");
        } else {
            System.out.println("插入失败");
        }
        ps.close();
        conn.close();
    }

    @Test
    public void update() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl",
                "scott",
                "tiger"
        );
        String sql = "update emp set sal = sal + ?, comm = comm + ? where " +
                "ename = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setDouble(1, 400);
        ps.setDouble(2, 300);
        ps.setString(3, "ALLEN");
        int i = ps.executeUpdate();
        if (i > 0) {
            System.out.println("成功修改" + i + "条数据");
        } else {
            System.out.println("修改失败");
        }
        ps.close();
        conn.close();
    }

    @Test
    public void insert2() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl",
                "scott",
                "tiger"
        );
        String sql = "delete from emp where empno = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1, 7999);
        int i = ps.executeUpdate();
        if (i > 0) {
            System.out.println("成功删除" + i + "条数据");
        } else {
            System.out.println("删除失败");
        }
        ps.close();
        conn.close();
    }

    @Test
    public void select() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl",
                "scott",
                "tiger"
        );
        String sql = "select * from emp where ename like ? and job = ? and " +
                "hireDate<=? and deptno = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1,"%M%");
        ps.setString(2,"CLERK");
        ps.setDate(3, Date.valueOf("2021-9-29"));
        ps.setInt(4,20);
        ResultSet rs = ps.executeQuery();
        while (rs.next()){
            System.out.println(rs.getString(1)+ "\t"
                            +rs.getString(2)+"\t"
                    + rs.getString(3) +"\t"+rs.getInt(4));
        }
        System.out.println("完成");
        rs.close();
        ps.close();
        conn.close();
    }
}

封装后的增删改查

接下来我们创建的包要分成这三个,dao,javabean,utils。

dao包下放的是有关数据库操作的实现类和接口,比如实现增删改某一条数据或者查询某一个表的操作;javabean下存放的是数据库操作的实体,比如要操作一个表,一个视图等;utils下存放的是工具类,这种工具类是Oracle操作共用的,不是针对一个表或者一个视图的,比如连接数据库,关闭各种数据库对象这些操作。

数据库对象封装另一个对象unable to resolve 数据库对象_oracle_02


首先我们在oracle的scott账户下创建一个病人表,用来当作例子。

这里有很多字段可以操作,比如number对应的Java中的int类型,varchar就对应String类型,date可以使用数据库厂商(这里是oracle)提供的类型。

//创建表的sql语句
 create table patientinfo(
        pid number(4) primary key,
        pname varchar(10) not null,
        sex char(2) default '男' check(sex='男' or sex='女') ,
        age number(3,0),
        tel varchar(11) unique,
        address varchar(50) default '沈阳',
        time date
        );

在utils包下创建一个工具类,这里封装了连接数据库和关闭数据库的必备操作。

package com.symc.example3.utils;

import java.sql.*;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/09/30 21:30
 * @Description: 将一些oracle的jdbc必须使用的步骤(如加载驱动,获取连接)封装起来,通过
 * 类名.方法名 的形式直接调用,以避免我们重复写这些步骤
 * 这里巧用的static静态块,它的特点是调用类方法前会执行static块内的代码,并且只会执行一次
 * 需要了解的是,这里已经指定资源和账户,如果你常用其他的账户,你可以将类改为抽象类,将
 * 将username和password变为抽象变量,这样你就可以通过写子类重写以获取其他的账户的工具
 */
public class JDBCUtils {
    /**
     * 创建连接资源的静态变量
     */
    private static String className = "oracle.jdbc.driver.OracleDriver";
    private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
    private static String username = "scott";
    private static String password = "tiger";

    /**
     *     驱动加载
     */
    static {
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建方法,获取连接对象
     *
     * @return Connection
     */
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException throwable) {
            throwable.printStackTrace();
            throw new RuntimeException("数据库连接错误!");
        }
    }

    /**
     * 关闭连接,释放资源
     * 由于我们使用的情况可能不同,使用查询时需要ResultSet对象,所以这里使用方法重载来适应
     * 各种应用场景
     */
    public static void closeAll(Connection conn, Statement sta) {
        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void closeAll(ResultSet rs, Connection conn, Statement sta) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

然后再javabean包下创建要操作的实体——病人信息表。
把属性都私有化,并创建getter、setter方法,也可以加上构造器;重写toString方法以方便后面我们查看记录信息。

package com.symc.example3.javabean;


import java.sql.Date;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/01 13:59
 * @Description: 创建病人信息(实体)
 */
public class PatientInfo {
    private int pid;
    private String pname;
    private String sex;
    private int age;
    private String tel;
    private String address;
    private Date time;//这里要注意导入的时间是那个包的

    public PatientInfo(){};

    public PatientInfo(int pid, String pname, String sex, int age, String tel,
                       String address, String time) {
        this.pid = pid;
        this.pname = pname;
        this.sex = sex;
        this.age = age;
        this.tel = tel;
        this.address = address;
        this.time = Date.valueOf(time);
    }

    public int getPid() {
        return pid;
    }

    public void setPid(int pid) {
        this.pid = pid;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    @Override
    public String toString() {
        return "PatientInfo{" +
                "pid=" + pid +
                ", pname='" + pname + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", tel='" + tel + '\'' +
                ", address='" + address + '\'' +
                ", time=" + time +
                '}';
    }
}

创建封装增删改查的接口

package com.symc.example3.dao;

import com.symc.example3.javabean.PatientInfo;

import java.sql.SQLException;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/01 14:07
 * @Description: 封装CURD操作 dao接口
 */
public interface PatientInfoDao {
    /**
     * 添加病人信息,新建
     * 修改病人信息
     * 删除病人信息 删除仅仅需要知道局部的信息就可以,这里传参用pid
     * 查询病人信息 查询方式多种可以用方法重载来实现
     */
    public int addPatientInfo(PatientInfo patientInfo) throws SQLException;

    public int updatePatientInfo(PatientInfo patientInfo) throws SQLException;

    public int deletePatientInfo(int pid) throws SQLException;

    public PatientInfo[] selectPatientInfo(String pname) throws SQLException;

}

实现接口,即实现增删改查功能

package com.symc.example3.dao;

import com.symc.example3.javabean.PatientInfo;
import com.symc.example3.utils.JDBCUtils;

import javax.print.attribute.standard.PrinterName;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/01 14:30
 * @Description: 实现封装的CURD操作
 */
public class PatientInfoDaoImpl implements PatientInfoDao {

    /**
     * 重写了添加病人信息的方法,这个病人信息就是PatientInfo的对象
     * @param patientInfo
     * @return i 执行一次所以返回的是1
     * @throws SQLException
     */
    @Override
    public int addPatientInfo(PatientInfo patientInfo) throws SQLException {
        //1.连接
        Connection conn = JDBCUtils.getConnection();
        //2.创建sql语句
        String sql = "insert into patientInfo values(?,?,?,?,?,?,?)";
        //3.创建预编译对象
        PreparedStatement ps = conn.prepareStatement(sql);
        //4.给占位符设置值
        ps.setInt(1,patientInfo.getPid());
        ps.setString(2,patientInfo.getPname());
        ps.setString(3,patientInfo.getSex());
        ps.setInt(4,patientInfo.getAge());
        ps.setString(5,patientInfo.getTel());
        ps.setString(6,patientInfo.getAddress());
        ps.setDate(7,patientInfo.getTime());
        //5.执行sql语句
        int i = ps.executeUpdate();
        //5.关闭连接,释放资源
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    /**
     * 这里修改信息,是通过主键pid来修改pname
     * @param patientInfo
     * @return i
     * @throws SQLException
     */
    @Override
    public int updatePatientInfo(PatientInfo patientInfo) throws SQLException {
        Connection conn = JDBCUtils.getConnection();
        String sql = "update patientInfo set pname = ? where pid = ? ";
        PreparedStatement ps = conn.prepareStatement(sql);
//        ps.setString(1,"pname");//这个占位符并不能设置字段名
        ps.setString(1,patientInfo.getPname());
        ps.setInt(2,patientInfo.getPid());
        int i = ps.executeUpdate();
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    @Override
    public int deletePatientInfo(int pid) throws SQLException {
        Connection conn = JDBCUtils.getConnection();
        String sql = "delete from patientInfo where pid = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1,pid);
        int i = ps.executeUpdate();
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    /**
     * 这里用数组来批量返回
     * 数组的长度就是返回结果集数据的条数
     * 如何设置数组的长度?结果集有一个游标,游标在哪所对应的就是第几条数据
     * 所以先将游标放到最后一条,就可以知道一共有多少条数据,也就确定了数组的大小
     * @param name
     * @return
     * @throws SQLException
     */
    @Override
    public PatientInfo[] selectPatientInfo(String name) throws SQLException {
        //1.获取连接对象
        Connection conn = JDBCUtils.getConnection();
        //2.编写查询语句
        String sql = "select * from patientInfo where pname = ?";
        //3.创建预编译对象
        //TYPE_SCROLL_SENSITIVE 设置游标可以双向滚动
        //默认鼠标是无法双向滚动的,所以这里加入这个值1005这样我们就可以将游标放到最后
        //CONCUR_UPDATABLE 可以更新ResultSet数据
        PreparedStatement ps = conn.prepareStatement(sql,
                ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
        //4.给占位符设置值
        ps.setString(1,name);
        //5.执行sql语句并拿到结果集
        ResultSet rs = ps.executeQuery();
        //先将游标移动到最后
        rs.last();
        //获取行数
        int length = rs.getRow();
        //游标返回到最开始的位置
        rs.beforeFirst();
        //创建数组
        PatientInfo[] pis = new PatientInfo[length];
        int index = 0;
        while (rs.next()){
            //创建实体对象
            PatientInfo pi = new PatientInfo();
            pi.setPid(rs.getInt(1));
            pi.setPname(rs.getString(2));
            pi.setSex(rs.getString(3));
            pi.setAge(rs.getInt(4));
            pi.setTel(rs.getString(5));
            pi.setAddress(rs.getString(6));
            pi.setTime(rs.getDate(7));
            //把封装好的实体放入对象数组
            pis[index++] = pi;
        }
        //6.关闭
        JDBCUtils.closeAll(rs,conn,ps);
        //返回对象数组
        return pis;
    }
}

最后,就可以测试功能了,在test目录下创建测试类,并打上@Test

import com.symc.example3.dao.PatientInfoDaoImpl;
import com.symc.example3.dao.PatientInfoDaoImplPro;
import com.symc.example3.javabean.PatientInfo;
import com.symc.example3.utils.JDBCUtils;
import org.junit.Test;

import java.sql.Date;
import java.sql.SQLException;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/01 14:53
 * @Description:
 */
public class Oracle_CURD_Test {

    /**
     * 创建PatientInfoDaoImpl实现类对象
     */
    PatientInfoDaoImpl pid = new PatientInfoDaoImpl();

    /**
     * 测试插入数据
     */
    @Test
    public void insert() throws SQLException {
        PatientInfo pi = new PatientInfo(1002, "张三", "男", 20, "16373894032",
                "沈阳医学院", "2021-10-01");
        int i = pid.addPatientInfo(pi);
        if (i > 0) {
            System.out.println("成功插入" + i + "条数据!");
        } else {
            System.out.println("插入失败!");
        }
    }

    @Test
    public void update() throws SQLException {
        PatientInfo pi = new PatientInfo();
        pi.setPid(1001);
        pi.setPname("李四");
        int i = pid.updatePatientInfo(pi);
        if (i > 0) {
            System.out.println("成功修改" + i + "条数据");
        } else {
            System.out.println("修改失败!");
        }
    }

    /**
     * 删除就不需要创建记录了,也就不用创建PatientInfo对象
     */
    @Test
    public void delete() throws SQLException {
        int i = pid.deletePatientInfo(1002);
        if (i > 0) {
            System.out.println("成功删除" + i + "条数据");
        } else {
            System.out.println("删除失败");
        }
    }

    @Test
    public void select() throws SQLException{
        for (PatientInfo patientInfo : pid.selectPatientInfo("小明")) {
            System.out.println(patientInfo.toString());
        }
    }

    /**
     * 这里主键pid和tel是唯一的,所以我们必须将它们设置为动态的
     * 每次只需要改变startNo和StartTel的值,就可以连续创建记录
     * 你也可以给它设置成自动输入,并且修改步长(默认1)、创建数量(默认5)
     * @throws SQLException
     */
    @Test
    public void insertInBulk() throws SQLException {
        PatientInfo pi = new PatientInfo();
        pi.setPname("小明");
        pi.setSex("男");
        pi.setAge(20);
//        pi.setTel("15521213320");//唯一约束,使得它为动态
        pi.setAddress("沈阳医学院");
        pi.setTime(Date.valueOf("2021-10-01"));

        int startNo = 1005;//设置初始主键
        int startTel = 10;
        int count = 0;
        int i = 0;
        for (int j = 0; j < 5; j++) {
            pi.setPid(startNo++);
            pi.setTel("123456789"+ startTel++);
            i = pid.addPatientInfo(pi);
            count += i;
            if (i > 0) {
                System.out.println("成功插入" + i + "条数据!");
            } else {
                System.out.println("插入失败!");
            }
        }
        System.out.println("共成功插入" + count + "条数据");
    }
}

代码优化

我们之前的代码还可以优化,敲了很多代码后,我们发现增删改的操作其实都差不多,就sql语句不一致,所以可以把增删改的一些操作再封装到一起,查询操作很多不同,需要另外封装个方法。
具体操作是,在JDBCUtils类中添加这两个方法

/**
     * 创建增删改的优化代码
     */
    public static int executeUpdate(String sql ,Object[] param) throws SQLException {
        Connection conn = getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        int i = ps.executeUpdate();
        closeAll(conn,ps);
        return i;
    }

    /**
     * 创建查询的优化代码
     */
    public static ResultSet executeQuery(Connection conn,PreparedStatement ps
            ,String sql,Object[] param) throws SQLException{
        conn = getConnection();
        ps = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,
                ResultSet.CONCUR_UPDATABLE);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        ResultSet rs = ps.executeQuery();
        return rs;
    }

接着再创建一个实现类,再重写一下接口。

package com.symc.example3.dao;

import com.symc.example3.javabean.PatientInfo;
import com.symc.example3.utils.JDBCUtils;

import javax.print.attribute.standard.PrinterName;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/01 14:30
 * @Description: 实现封装的CURD操作
 */
public class PatientInfoDaoImpl implements PatientInfoDao {

    /**
     * 重写了添加病人信息的方法,这个病人信息就是PatientInfo的对象
     * @param patientInfo
     * @return i 执行一次所以返回的是1
     * @throws SQLException
     */
    @Override
    public int addPatientInfo(PatientInfo patientInfo) throws SQLException {
        //1.连接
        Connection conn = JDBCUtils.getConnection();
        //2.创建sql语句
        String sql = "insert into patientInfo values(?,?,?,?,?,?,?)";
        //3.创建预编译对象
        PreparedStatement ps = conn.prepareStatement(sql);
        //4.给占位符设置值
        ps.setInt(1,patientInfo.getPid());
        ps.setString(2,patientInfo.getPname());
        ps.setString(3,patientInfo.getSex());
        ps.setInt(4,patientInfo.getAge());
        ps.setString(5,patientInfo.getTel());
        ps.setString(6,patientInfo.getAddress());
        ps.setDate(7,patientInfo.getTime());
        //5.执行sql语句
        int i = ps.executeUpdate();
        //5.关闭连接,释放资源
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    /**
     * 这里修改信息,是通过主键pid来修改pname
     * @param patientInfo
     * @return i
     * @throws SQLException
     */
    @Override
    public int updatePatientInfo(PatientInfo patientInfo) throws SQLException {
        Connection conn = JDBCUtils.getConnection();
        String sql = "update patientInfo set pname = ? where pid = ? ";
        PreparedStatement ps = conn.prepareStatement(sql);
//        ps.setString(1,"pname");//这个占位符并不能设置字段名
        ps.setString(1,patientInfo.getPname());
        ps.setInt(2,patientInfo.getPid());
        int i = ps.executeUpdate();
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    @Override
    public int deletePatientInfo(int pid) throws SQLException {
        Connection conn = JDBCUtils.getConnection();
        String sql = "delete from patientInfo where pid = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1,pid);
        int i = ps.executeUpdate();
        JDBCUtils.closeAll(conn,ps);
        return i;
    }

    /**
     * 这里用数组来批量返回
     * 数组的长度就是返回结果集数据的条数
     * 如何设置数组的长度?结果集有一个游标,游标在哪所对应的就是第几条数据
     * 所以先将游标放到最后一条,就可以知道一共有多少条数据,也就确定了数组的大小
     * @param name
     * @return
     * @throws SQLException
     */
    @Override
    public PatientInfo[] selectPatientInfo(String name) throws SQLException {
        //1.获取连接对象
        Connection conn = JDBCUtils.getConnection();
        //2.编写查询语句
        String sql = "select * from patientInfo where pname = ?";
        //3.创建预编译对象
        //TYPE_SCROLL_SENSITIVE 设置游标可以双向滚动
        //默认鼠标是无法双向滚动的,所以这里加入这个值1005这样我们就可以将游标放到最后
        //CONCUR_UPDATABLE 可以更新ResultSet数据
        PreparedStatement ps = conn.prepareStatement(sql,
                ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
        //4.给占位符设置值
        ps.setString(1,name);
        //5.执行sql语句并拿到结果集
        ResultSet rs = ps.executeQuery();
        //先将游标移动到最后
        rs.last();
        //获取行数
        int length = rs.getRow();
        //游标返回到最开始的位置
        rs.beforeFirst();
        //创建数组
        PatientInfo[] pis = new PatientInfo[length];
        int index = 0;
        while (rs.next()){
            //创建实体对象
            PatientInfo pi = new PatientInfo();
            pi.setPid(rs.getInt(1));
            pi.setPname(rs.getString(2));
            pi.setSex(rs.getString(3));
            pi.setAge(rs.getInt(4));
            pi.setTel(rs.getString(5));
            pi.setAddress(rs.getString(6));
            pi.setTime(rs.getDate(7));
            //把封装好的实体放入对象数组
            pis[index++] = pi;
        }
        //6.关闭
        JDBCUtils.closeAll(rs,conn,ps);
        //返回对象数组
        return pis;
    }
}

最后在测试类中测试代码

/**
     * 优化代码的测试
     */
    PatientInfoDaoImplPro pid1 = new PatientInfoDaoImplPro();
    @Test
    public void insert1() throws SQLException {
        PatientInfo pi = new PatientInfo(1002, "张三", "男", 20, "16373894032",
                "沈阳医学院", "2021-10-01");
        int i = pid1.addPatientInfo(pi);
        if (i > 0) {
            System.out.println("成功插入" + i + "条数据!");
        } else {
            System.out.println("插入失败!");
        }
    }

    @Test
    public void update1() throws SQLException {
        PatientInfo pi = new PatientInfo();
        pi.setPid(1002);
        pi.setPname("李四");
        int i = pid1.updatePatientInfo(pi);
        if (i > 0) {
            System.out.println("成功修改" + i + "条数据");
        } else {
            System.out.println("修改失败!");
        }
    }

    @Test
    public void delete1() throws SQLException {
        int i = pid1.deletePatientInfo(1002);
        if (i > 0) {
            System.out.println("成功删除" + i + "条数据");
        } else {
            System.out.println("删除失败");
        }
    }

    @Test
    public void select1() throws SQLException{
        PatientInfo[] pis = pid1.selectPatientInfo("小明");
        for (PatientInfo pi : pis) {
            System.out.println(pi.toString());
        }
    }

实现同时操作多个数据库

假如现在本机的oracle和mysql都有一样的emp表,现在想要将一条数据插入到两个数据库,只需要写一份代码就能实现,那应该怎么做呢?

首先,依旧是建立三包,结构如下

数据库对象封装另一个对象unable to resolve 数据库对象_oracle_03


先在javabean下创建实体类Emp(表)

package com.symc.example4.javabean;

import java.util.Date;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/02 20:24
 * @Description: Emp表 同时操作多个数据
 */
public class Emp {

    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hireDate;
    private Double sal;
    private Double comm;
    private Integer deptno;

    public Emp() {
    }

    public Emp(Integer empno, String ename, String job, Integer mgr,
               Date hireDate, Double sal, Double comm, Integer deptno) {
        this.empno = empno;
        this.ename = ename;
        this.job = job;
        this.mgr = mgr;
        this.hireDate = hireDate;
        this.sal = sal;
        this.comm = comm;
        this.deptno = deptno;
    }

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

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

    public String getJob() {
        return job;
    }

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

    public Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHireDate() {
        return hireDate;
    }

    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Double getComm() {
        return comm;
    }

    public void setComm(Double comm) {
        this.comm = comm;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

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

在dao包下创建一个数据库操作类的抽象类,后面Oracle实现类和Mysql实现类都是继承这个类。

package com.symc.example4.dao;

import com.symc.example4.javabean.Emp;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/02 20:34
 * @Description: 数据库增删改查emp表抽象类
 */
public abstract class DataBaseDao {

    public abstract int insertEmp(Emp emp) throws Exception;

    public abstract int updateEmp(Emp emp) throws Exception;

    public abstract int deleteEmpByEmpNo(int empNo) throws Exception;

    public abstract Emp[] selectEmpByCondition(Emp emp) throws Exception;
}

在utils包下创建两个数据库的工具类

package com.symc.example4.utils;

import java.sql.*;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/2 21:30
 * @Description: 将一些oracle的jdbc必须使用的步骤(如加载驱动,获取连接)封装起来,通过
 * 类名.方法名 的形式直接调用,以避免我们重复写这些步骤
 * 这里巧用的static静态块,它的特点是调用类方法前会执行static块内的代码,并且只会执行一次
 * 需要了解的是,这里已经指定资源和账户,如果你常用其他的账户,你可以将类改为抽象类,将
 * 将username和password变为抽象变量,这样你就可以通过写子类重写以获取其他的账户的工具
 */
public class JDBCUtils_oracle {
    /**
     * 创建连接资源的静态变量
     */
    private static String className = "oracle.jdbc.driver.OracleDriver";
    private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
    private static String username = "scott";
    private static String password = "tiger";

    /**
     *     驱动加载
     */
    static {
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建方法,获取连接对象
     *
     * @return Connection
     */
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException throwable) {
            throwable.printStackTrace();
            throw new RuntimeException("数据库连接错误!");
        }
    }

    /**
     * 关闭连接,释放资源
     * 由于我们使用的情况可能不同,使用查询时需要ResultSet对象,所以这里使用方法重载来适应
     * 各种应用场景
     */
    public static void closeAll(Connection conn, Statement sta) {
        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void closeAll(ResultSet rs, Connection conn, Statement sta) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    /**
     * 创建增删改的优化代码
     */
    public static int executeUpdate(String sql ,Object[] param) throws SQLException {
        Connection conn = getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        int i = ps.executeUpdate();
        closeAll(conn,ps);
        return i;
    }

    /**
     * 创建查询的优化代码
     */
    public static ResultSet executeQuery(Connection conn,PreparedStatement ps
            ,String sql,Object[] param) throws SQLException{
        conn = getConnection();
        ps = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,
                ResultSet.CONCUR_UPDATABLE);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        ResultSet rs = ps.executeQuery();
        return rs;
    }
}

这个是mysql的

package com.symc.example4.utils;

import java.sql.*;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/2 21:30
 * @Description: mysql的工具类
 */
public class JDBCUtils_mysql {
    /**
     * 创建连接资源的静态变量
     */
    private static String className = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/bookstore" +
            "?characterEncoding=utf-8" ;
    private static String username = "root";
    private static String password = "1234";

    /**
     *     驱动加载
     */
    static {
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建方法,获取连接对象
     *
     * @return Connection
     */
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException throwable) {
            throwable.printStackTrace();
            throw new RuntimeException("数据库连接错误!");
        }
    }

    /**
     * 关闭连接,释放资源
     * 由于我们使用的情况可能不同,使用查询时需要ResultSet对象,所以这里使用方法重载来适应
     * 各种应用场景
     */
    public static void closeAll(Connection conn, Statement sta) {
        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void closeAll(ResultSet rs, Connection conn, Statement sta) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (sta != null) {
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    /**
     * 创建增删改的优化代码
     */
    public static int executeUpdate(String sql ,Object[] param) throws SQLException {
        Connection conn = getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        int i = ps.executeUpdate();
        closeAll(conn,ps);
        return i;
    }

    /**
     * 创建查询的优化代码
     */
    public static ResultSet executeQuery(Connection conn,PreparedStatement ps
            ,String sql,Object[] param) throws SQLException{
        conn = getConnection();
        ps = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,
                ResultSet.CONCUR_UPDATABLE);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i+1,param[i]);
            }
        }
        ResultSet rs = ps.executeQuery();
        return rs;
    }
}

分别在Oracle和Mysql实现抽象类DataDaseDao,
OracleDaoImpl、MyDaoImpl
这里只写OracleDaoImpl,两个基本是一样的操作

package com.symc.example4.dao;

import com.symc.example4.javabean.Emp;
import com.symc.example4.utils.JDBCUtils_oracle;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/02 20:41
 * @Description:
 */
public class OracleDaoImpl extends DataBaseDao {
    @Override
    public int insertEmp(Emp emp) throws Exception {
        int i = JDBCUtils_oracle.executeUpdate("insert into emp values(?,?,?," +
                        "?,?," +
                        "?,?,?)",
                new Object[]{emp.getEmpno(), emp.getEname(),
                        emp.getJob(), emp.getMgr(), emp.getHireDate(), emp.getSal(),
                        emp.getComm(), emp.getDeptno()
                });
        return i;
    }

    @Override
    public int updateEmp(Emp emp) throws Exception {
        int i = JDBCUtils_oracle.executeUpdate("update emp set sal = sal + ?,comm = " +
                "comm + ? where ename = ?", new Object[]{
                emp.getSal(), emp.getComm(), emp.getEname()
        });
        return i;
    }

    @Override
    public int deleteEmpByEmpNo(int empNo) throws Exception {
        int i = JDBCUtils_oracle.executeUpdate("delete from emp where empno = ?",
                new Object[]{empNo});
        return i;
    }

    @Override
    public Emp[] selectEmpByCondition(Emp emp) throws Exception {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = JDBCUtils_oracle.executeQuery(conn, ps, "select * from emp where " +
                "sal>?", new Object[]{emp.getSal()});
        rs.last();
        Emp[] emps = new Emp[rs.getRow()];
        rs.beforeFirst();
        int index = 0;
        for (int i = 0; i < emps.length; i++) {
            while (rs.next()){
                Emp emp1 = new Emp();
                emp1.setEmpno(rs.getInt(1));
                emp1.setEname(rs.getString(2));
                emp1.setJob(rs.getString(3));
                emp1.setMgr(rs.getInt(4));
                emp1.setHireDate(rs.getDate(5));
                emp1.setSal(rs.getDouble(6));
                emp1.setComm(rs.getDouble(7));
                emp1.setDeptno(rs.getInt(8));
                emps[index++] = emp1;
            }
        }
        JDBCUtils_oracle.closeAll(rs,conn,ps);
        return emps;
    }
}

最后创建一个测试类测试一下

import com.symc.example4.dao.DataBaseDao;
import com.symc.example4.dao.OracleDaoImpl;
import com.symc.example4.javabean.Emp;
import org.junit.Test;

/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/10/02 20:55
 * @Description:
 */
public class DataBaseTest {
    /**
     * 创建子类对象
     */
    DataBaseDao baseDao = new OracleDaoImpl();

    @Test
    public void insert() throws Exception{
        Emp emp = new Emp();
        emp.setEmpno(new Integer(9000));
        emp.setEname("张三");
        emp.setJob("CLERK");
        emp.setMgr(7698);
        emp.setHireDate(java.sql.Date.valueOf("2021-10-1"));
        emp.setSal(3000d);
        emp.setComm(500d);
        emp.setDeptno(20);
        int i = baseDao.insertEmp(emp);
        System.out.println(i);
    }

    @Test
    public void update() throws Exception{
        Emp emp = new Emp();
        emp.setSal(100d);
        emp.setComm(200d);
        emp.setEname("张三");
        int i = baseDao.updateEmp(emp);
        System.out.println(i);
    }

    @Test
    public void delete() throws Exception{
        Integer empNo = new Integer(9000);
        int i = baseDao.deleteEmpByEmpNo(empNo);
        System.out.println(i);
    }

    @Test
    public void select() throws Exception{
        Emp emp = new Emp();
        emp.setSal(3000d);
        Emp[] emps = baseDao.selectEmpByCondition(emp);
        for (Emp emp1 : emps) {
            System.out.println(emp1.toString());
        }
    }
}