JDBC-Data Acess Object

Posted Vodka~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC-Data Acess Object相关的知识,希望对你有一定的参考价值。

//BaseDAO.java
package DAO;
import Instrument.GetConnection;
import User.CetStu;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @description 一个基类里面,封装了针对不同数据表的通用操作,子类继承基类,
 * @author Vodka
 * @date 2021/07//18:01
 */

public  class  BaseDAO <T> {
//    因为是针对具体某个表的具体操作,不需要利用反射动态获取表的相应类,可以在继承时直接声明T的类,泛型方法也要改回泛型类的泛型
    private Class<T> TClass  = null;

    //1.{...}构造块,只有类建造一个对象,构造代码块就执行一次
    //2.static{...}静态构造块,建立一个对象,就只执行一次
    //3.构造块的代码放在基类里,这样不同子类继承只需要声明T的类型,不用重复写构造块,减少冗余
 {
     /*
* -Type是所有数据类型的公共高级接口,所有已知子接口:GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType
  所有已知实现类:Class
  * -注意区分Type与Class的区别,这里的Class是Type的一种,而像数组、枚举等"类型"是相对于Class来说的。
* -Type[]    getActualTypeArguments()  返回表示此类型实际类型参数的 Type 对象的数组。
*-简单来说就是:获得参数化类型中<>里的类型参数的类型。
*   因为可能有多个类型参数,例如Map<K, V>,所以返回的是一个Type[]数组。
*-注意:无论<>中有几层<>嵌套,这个方法仅仅脱去最外层的<>,
*   之后剩下的内容就作为这个方法的返回值,所以其返回值类型不一定。
*
* */
      //getGenericSuperclass(),作用是获取父类及其泛型,例子:Person<Teacher,Doctor>
     // getSuperclass(),区别是获取父类,但没有泛型参数类型 , 例子: Person<>
     //这里的this不是BaseDAO, 是具体子类,通过具体子类获取父类的泛型参数类型数组
     Type GSC = this.getClass().getGenericSuperclass();
     //获取参数化类型中<>里的类型参数的类型数组
     Type[] TypeArgs = ((ParameterizedType)GSC).getActualTypeArguments();
    //这里只有一个泛型参数,所有只需要泛型参数数组的第一个元素即可,要类型转换
     TClass = (Class<T>) TypeArgs[0];
 }

    //考虑事务特性的增删改操作,version 2.0
    public  int UpdateTwo(Connection conn, String sql, Object...args) {
        PreparedStatement ps = null;
        int ExecuteRS = 0;
        try {
            //预编译
            ps = conn.prepareStatement(sql);
            for (int index = 0; index < args.length; index++) {
                ps.setObject(index + 1, args[index]);   //这里要注意两个变量下标起始值的不同
            }
            //执行sql语句
            /*
             *   对于ps.execute():
             *      1.如果执行的是查询操作,查询成功就返回true
             *      2.如果执行的是增删改,失败就返回false
             *   对于ps.executeUpdate():
             *      1.执行增删改成功,就返回DML操作的行数,失败就什么都不返回
             *
             * */
            ExecuteRS = ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //数据库的连接关闭交由函数外部的代码控制,这样可以保证一个事务完整性,一次连接贯穿一次事务
                GetConnection.Close(null, ps);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return ExecuteRS;
    }

    //查询函数,返回查询结果
    public List<T> TableSearch( String sql, Object... arg) {

        //这里利用反射的Class,用来动态获取具体的表的相应的类,再根据反射获得的类来创建相应的对象
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        ArrayList<T> TList = null;
        try {

            conn = GetConnection.getConnection();
            ps = conn.prepareStatement(sql);
            //填充查询语句中的占位符
            for (int index = 0; index < arg.length; ++index) {
                ps.setObject(index + 1, arg[index]);
            }

            //执行查询操作,使用Result的实例对象来接收查询结果集
            resultSet = ps.executeQuery();
            //从结果集中获取数据库相应表的元数据(即数据类型),以及(元数据的个数)表的列数
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int ColumnNums = rsmd.getColumnCount();
            TList = new ArrayList<>();

            //遍历结果集
            while (resultSet.next()) {
                //利用泛型类直接创建的对象,代替反射的动态获取相应类再创建实例对象
                T temp = TClass.getDeclaredConstructor().newInstance();
                //遍历每一列,获取数据
                for (int index = 0; index < ColumnNums; ++index) {
                    //通过ResultSet获取每一列的值
                    Object ColumnValue = resultSet.getObject(index + 1);
                    //通过rsmd,获取相应的列名,getColumnLabel()该方法既能获取列名,也可以获取列的别名
                    String ColumnLabel = rsmd.getColumnLabel(index + 1);
                    //通过列名获取其在相应类中的属性域
                    Field field = temp.getClass().getDeclaredField(ColumnLabel);
                    field.setAccessible(true);  // 当要修改不是public的属性时,要设置为truee
                    field.set(temp, ColumnValue);
                }
                //添加到表的集合对象中
                TList.add(temp);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                GetConnection.CloseResource(conn, ps, resultSet);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //返回包含所有查询对象的集合
        return TList;
    }

    //针对只返回一行查询结果的情况,如sql聚集函数的结果
    public <E> E GetOneValue(E data, Connection conn, String sql, Object...args){
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
            ps = conn.prepareStatement(sql);
            for( int index = 0 ; index < args.length; ++index){
                ps.setObject(index+1,args[index]);
            }
            rs = ps.executeQuery();
            if(rs.next()){
                return (E) rs.getObject(1); //转换成E类型的数据结果,并返回
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //当前连接不关闭,交由外部开启连接的程序关闭,这样可以避免一个事务的全部操作尚未结束,就关闭了连接的问题
            try {
                GetConnection.CloseResource(null,ps,rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return null;
    }
}

//CET表的接口
package DAO;
import User.CetStu;
import java.sql.Connection;
import java.util.Date;
import java.util.List;

/**
 * @author Vodka
 * @date 2021/07//18:11
 * @description 此接口用于规针对于CET表的通用操作
 */
public interface CET {
//      将cet对象添加到数据库中
   void InCET(Connection conn, CetStu cet);

//      根据FlowId删除记录
    void DeleteById(Connection conn,int FlowId );

    //根据内存中的cet对象,去修改表中的数据
    void update(Connection conn,CetStu cet);

//    根据FlowId 查询对应的CetStu对象
    CetStu QueryStu(Connection conn,int FlowId);

//    查询表中所有记录的集合
    List<CetStu> QueryAll(Connection conn);

//    返回数据表中总数据条数
    long NumOfTable(Connection conn);

//    返回学生中最大年龄
    Date MaxBirth(Connection conn);
}




//CETDAO.java
package Bean;
import DAO.*;
import User.*;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

/**
 * @description CET表的通用操作类,继承BaseDAO,实现CET的接口,面向接口编程(继承基类的方法,重写接口的方法)
 * @author Vodka
 * @date 2021/07//15:50
 */

//继承基类的时候,要声明基类泛型类的类型
public class CetDAO extends BaseDAO<CetStu> implements CET{
    @Override
    public void InCET(Connection conn, CetStu cet) {
        String sql ;
        sql = "Insert into cet ( Species, IDCard, ExamCard, StudentName, Location, Grade , InTime ) " +
                "values(?,?,?,?,?,?,?)";
        UpdateTwo(conn,sql,cet.getSpecies(),cet.getIDCard(),cet.getExamCard(),cet.getStudentName(),
                  cet.getLocation(),cet.getGrade(),cet.getInTime());
    }

    @Override
    public void DeleteById(Connection conn, int FlowId) {
         String sql = "Delete from cet where FlowId = ?";
         UpdateTwo(conn,sql,FlowId);
    }

    @Override
    public void update(Connection conn, CetStu cet) {
         String sql = "Update cet set Species = ? , IDCard = ? , ExamCard = ? , " +
                 "StudentName, = ?  Location = ? , Grade  = ? , InTime = ? where FlowId = ?";
         UpdateTwo(conn,sql,cet.getSpecies(),cet.getIDCard(),cet.getExamCard(),cet.getStudentName(),
                 cet.getLocation(),cet.getGrade(),cet.getInTime(),cet.getFLowId());
    }

    @Override
    public CetStu QueryStu(Connection conn, int FlowId) {
        String sql = "select * from cet where FlowId = ?";
       return (CetStu) TableSearch(sql,FlowId);
    }

    @Override
    public List<CetStu> QueryAll(Connection conn) {
       String sql = "select * from cet ";
       return TableSearch(sql);
    }

    @Override
    public long NumOfTable(Connection conn) {
        String sql = "select count(*) from cet";
        long i = 0;
        return GetOneValue(i,conn,sql);
    }

    @Override
    public Date MaxBirth(Connection conn) {
        String sql = "select Max(InTime) from cet";
        Date d = null;
        return GetOneValue(d,conn,sql);
    }
}


//CetStu.java  CET表的相应类
private String IDCard;
    private String ExamCard;
    private String StudentName;
    private String Location;

    public CetStu(){
        super();
    }

    public CetStu( int species, int grade, Timestamp inTime, String IDCard, String examCard, String studentName, String location) {

        Species = species;
        Grade = grade;
        InTime = inTime;
        this.IDCard = IDCard;
        ExamCard = examCard;
        StudentName = studentName;
        Location = location;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CetStu cetStu = (CetStu) o;
        return FLowId == cetStu.FLowId &&
                Species == cetStu.Species &&
                Grade == cetStu.Grade &&
                Objects.equals(InTime, cetStu.InTime) &&
                Objects.equals(IDCard, cetStu.IDCard) &&
                Objects.equals(ExamCard, cetStu.ExamCard) &&
                Objects.equals(StudentName, cetStu.StudentName) &&
                Objects.equals(Location, cetStu.Location);
    }

    @Override
    public int hashCode() {
        return Objects.hash(FLowId, Species, Grade, InTime, IDCard, ExamCard, StudentName, Location);
    }

    public void setFLowId(int FLowId) {
        this.FLowId = FLowId;
    }

    public void setSpecies(int species) {
        Species = species;
    }

    public void setGrade(int grade) {
        Grade = grade;
    }

    public void setInTime(Timestamp inTime) {
        InTime = inTime;
    }

    public void setIDCard(String IDCard) {
        this.IDCard = IDCard;
    }

    public void setExamCard(String examCard) {
        ExamCard = examCard;
    }

    public void setStudentName(String studentName) {
        StudentName = studentName;
    }

    public void setLocation(String location) {
        Location = location;
    }

    public int getFLowId() {
        return FLowId;
    }

    public int getSpecies() {
        return Species;
    }

    public int getGrade() {
        return Grade;
    }

    public Timestamp getInTime() {
        return InTime;
    }

    public String getIDCard() {
        return IDCard;
    }

    public String getExamCard() {
        return ExamCard;
    }

    public String getStudentName() {
        return StudentName;
    }

    public String getLocation() {
        return Location;
    }

    @Override
    public String toString() {
        return "CetStu{ " +
                "FLowId=" + FLowId +
                ", Species=" + Species +
                ", Grade=" + Grade +
                ", InTime=" + InTime +
                ", IDCard='" + IDCard + '\\'' +
                ", ExamCard='" + ExamCard + '\\'' +
                ", StudentName='" + StudentName + '\\'' +
                ", Location='" + Location + '\\'' +
                '}';
    }
}



//CET测试类,测试相应方法
import java.util.List;
/**
 * @author Vodka
 * @date 2021/07//16:31
 */
public class CetDAOTest {
    //创建一个Cet通用操作类的对象
    private  CetDAO CDAO = new CetDAO();
    //测试最大年龄
    @Test
   public void testOne(){
        Connection conn = null;
        try {
            conn = GetConnection.getConnection();
            Date date = CDAO.MaxBirth(conn);
            System.out.println(date);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                GetConnection.Close(conn,null);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

   }

    //测试获取全部数据
    @Test
    public void testTwo(){
        Connection conn = null;
        try {
            conn = GetConnection.getConnection();
            List<CetStu> AllStu= CDAO.以上是关于JDBC-Data Acess Object的主要内容,如果未能解决你的问题,请参考以下文章

在本地预览可以,上传到服务器上怎么就一片空白?

LINQ to OBJECT函数积累

runtime????????????selector???????????????IMP???????????????????????????????????????????????????(代码片

html 来自JS的Acess变量

PyQt acess selectionChanged Content

如何在 Acess 2010 中制作每个月的案例类型计数报告