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的主要内容,如果未能解决你的问题,请参考以下文章
runtime????????????selector???????????????IMP???????????????????????????????????????????????????(代码片