当前位置: 首页 > 工具软件 > JdbcPlus > 使用案例 >

JDBCplus-JDBC框架

鄢子平
2023-12-01

JDBC框架

文章为上一篇扩展,需接上一篇进行阅读:JDBC基础

框架的背景

源信息:

1、ParameterMetaData :参数的源信息:

java.sql.ParameterMetaData封装的是预编译执行者对象中每个参数的类型和属性,这个对象可以通过预编译执行者对象中的

getParameterMetaData()方法来获取

核心功能: int getParameterCount()用于获取sql语句中参数的个数

2、ResultSetMetaData:结果集的源信息
java.sql.ResultSetMetaData :封装的是结果集对象中列的类型和属性,这个对象可以通过结果集对象中的getMetaData()方法来获取
核心功能: int getColumnCount()用于获取列的总数,String getColumnName(int i)用于获取列名

框架的编写

1.用于执行增删改功能的update()方法

步骤:

定义所需成员变量(数据源、数据库连接、执行者、结果集)。

定义有参构造,为数据源对象赋值。

定义update()方法,参数:sql语句、sql语句所需参数。

定义int类型变量,用于接收sql语句执行后影响的行数。

通过数据源获取一个数据库连接。

通过数据库连接对象获取执行者对象并对sql语句预编译。

通过执行者对象获取sql语句中参数的源信息对象。

通过参数源信息对象获取sql语句中参数的个数。

判断参数个数是否一致。

为sql语句中?占位符赋值。

执行sql语句并接收结果。

释放资源。

返回结果。

示例代码:

package JDBCframe;

import javax.sql.DataSource;
import java.sql.*;

public class JDBCtemplate {
//    1、定义参数变量(数据源、连接对象、执行者对象、结果集对象)
    private DataSource dataSource;
    private Connection con;
    private PreparedStatement pst;
    private ResultSet rs;
//    2、通过有参构造为数据源赋值

    public JDBCtemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

//    3、定义update方法
    public int update(String sql,Object...objs){
        //    4、定义int变量返回影响行数
        int result=0;
        try{
            //    5、通过数据源获取一个数据库连接
            con=dataSource.getConnection();
            //    6、通过连接对象获取执行者对象,对SQL语句进行预编译
            pst=con.prepareStatement(sql);
            //    7、通过执行者者对象获取参数的源信息对象
            ParameterMetaData pmd = pst.getParameterMetaData();
            //    8、参数的源信息对象获取参数个数
            int count = pmd.getParameterCount();
            //    9、判断参数个数十分一致
            if (count!=objs.length){
                throw new RuntimeException("参数个数不匹配");
            }
            //   10、为SQL语句占位符赋值
            for (int i = 0; i < objs.length; i++) {
                pst.setObject(i+1,objs[i]);
            }
            //    11、执行SQL语句
            result=pst.executeUpdate();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //  12、释放资源
            try {
                con.close();
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        //  13、返回结果
        return result;
    }
}

2.update()方法的测试。

定义测试类,模拟dao层。

测试执行insert语句。

测试执行update语句。

测试执行delete语句。

示例代码:

package JDBCframe;

import Druid.DruidUtils;
import org.testng.annotations.Test;

public class Test1 {
    private JDBCtemplate tem=new JDBCtemplate(DruidUtils.getDataSource());
    /*
    * 1、添加数据
    * */
    @Test
    public void insert(){
        String sql="insert into student values (?,?,?,?)";
        Object[] params={8,"罗",27,"1999-09-01"};
        int result = tem.update(sql, params);
        if (result==0){
            System.out.println("添加失败");
        }else {
            System.out.println("添加成功");
        }
    }
    /*
    * 2、删除数据
    * */
    @Test
    public void delete(){
        String sql="delete from student where id=?";
        Object[] params={8};
        int result = tem.update(sql, params);
        if (result==0){
            System.out.println("删除失败");
        }else {
            System.out.println("删除成功");
        }
    }
    /*
    * 3、修改数据
    * */
    @Test
    public void update(){
        String sql="update student set sname = ? where id=?";
        Object[] params={"罗锋",8};
        int result = tem.update(sql, params);
        if (result==0){
            System.out.println("修改失败");
        }else {
            System.out.println("修改成功");
        }
    }
}

3.用于执行查询功能的方法介绍。

查询一条记录并封装对象的方法:queryForObject()(以下仅展示这一个方法,核心方法。

查询多条记录并封装集合的方法:queryForList()

查询聚合函数并返回单条数据的方法:queryForScalar()

queryForObject()

实体类编写

注意一定要和数据库字段同名,不然后续无法加载到set方法。

package JDBCframe;

import java.util.Date;

public class Student {
    private Integer id;
    private String sname;
    private Integer age;
    private Date birthday;
    // 很重要,反射创建对象时需要
    public Student() {
    }
    
    public Student(Integer id, String sname, Integer age, Date birthday) {
        this.id = id;
        this.sname = sname;
        this.age = age;
        this.birthday = birthday;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}

处理结果集的接口

1、定义泛型接口ResultSetHandler。

2、定义用于处理结果集的泛型方法 T handler(Resultset rS)。

注意:此接口仅用于为不同处理结果集的方式提供规范,具体的实现类还需要自行编写。

示例代码:
package JDBCframe;

import java.sql.ResultSet;
/*
* 用于处理结果集规范的接口
* */
public interface ResultSetHandler <T>{
    <T> T handler(ResultSet rs);
}

接口实现类

将一条记录封装到自定义对象中

package JDBCframe;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Locale;

public class BeanHandler<T> implements ResultSetHandler<T>{
//  定义class对象
    private Class<T> beanClass;
//  有参构造赋值
    public BeanHandler(Class<T> beanClass) {
        this.beanClass = beanClass;
    }

    /*
    * 将一条记录封装到自定义对象中
    * */
    @Override
    public T handler(ResultSet rs) {
//        声明自定义对象类型
        T bean=null;

        try {
            //创建传递参数对象,为自定义对象赋值
            bean=beanClass.newInstance();
            //判断结果集中是否有数据
            if (rs.next()){
                //通过结果集对象获取结果集源信息对象
                ResultSetMetaData md = rs.getMetaData();
                //通过结果集源信息对象获取列数
                int count = md.getColumnCount();
                //  循环遍历列数
                for (int i = 1; i <= count; i++) {
                    // 通过结果集源信息对象获取列名
                    String columnName = md.getColumnName(i);
                    // 通过列名获取该列数据
                    Object value = rs.getObject(columnName);
                    // 创建属性描述器对象,对实体对象赋值
                    PropertyDescriptor pd=new PropertyDescriptor(columnName.toLowerCase(Locale.ROOT),beanClass);
                    //获取set方法
                    Method writeMethod = pd.getWriteMethod();
                    //执行set方法,给成员变量赋值
                    writeMethod.invoke(bean,value);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回封装好的对象
        return bean;
    }
}

用于查询一条记录并封装对象的方法queryForObject()。

定义方法queryForObject(),参数:sql语句、处理结果集接口、sql语句中的参数。

声明自定义类型对象。

通过数据源获取数据库连接对象。

通过数据库连接对象获取执行者对象并对sql语句进行预编译。

通过执行者对象获取参数源信息的对象。

通过参数源信息对象获取参数的个数。判断参数数量是否一致。

为sql语句中?占位符赋值。

执行sql语句并接收结果集。

通过结果集接口对结果进行处理。

释放资源。

返回结果。

示例代码:

package JDBCframe;

import javax.sql.DataSource;
import java.sql.*;

public class JDBCtemplate {
//    1、定义参数变量(数据源、连接对象、执行者对象、结果集对象)
    private DataSource dataSource;
    private Connection con;
    private PreparedStatement pst;
    private ResultSet rs;
//    2、通过有参构造为数据源赋值

    public JDBCtemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

//    定义查询方法
    public <T> T query(String sql,ResultSetHandler<T> rsh,Object...objs){
        T obj=null;
        try{
            //通过数据源获取一个数据库连接
            con=dataSource.getConnection();
            // 通过连接对象获取执行者对象,对SQL语句进行预编译
            pst=con.prepareStatement(sql);
            // 通过执行者者对象获取参数的源信息对象
            ParameterMetaData pmd = pst.getParameterMetaData();
            // 参数的源信息对象获取参数个数
            int count = pmd.getParameterCount();
            // 判断参数个数十分一致
            if (count!=objs.length){
                throw new RuntimeException("参数个数不匹配");
            }
            //为SQL语句占位符赋值
            for (int i = 0; i < objs.length; i++) {
                pst.setObject(i+1,objs[i]);
            }
            // 执行SQL语句
            rs=pst.executeQuery();
            //通过BeanHandler方式对结果集处理
            obj = rsh.handler(rs);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //  释放资源
            try {
                con.close();
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        //  返回结果
        return obj;
    }
}

测试:

/*
* 4、查询数据
* */
@Test
public void query(){
    String sql="select * from student where id=?";
    Student stu = tem.query(sql, new BeanHandler<>(Student.class), 1);
    System.out.println(stu);
}
 类似资料: