JDBC-通用查询(笔记)

package PreparedStatementCURD;
import User.UserInfo;
import org.junit.Test;
import util.GetConnection;

import java.awt.*;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;

/**
 * @author Vodka
 * @date 2021/07//16:18
 */
 /* ORM编程思想(Object relational mapping)
         * 一个数据表对象一个java类,表中的一条记录代表一个对象,一个字段代表java类的属性
         *    java类型                SQL类型
         *    1.boolean                bit
         *    2.byte                   tinyint
         *    3.short                  smallint
         *    4.int                    integer
         *    5.long                   bigint
         *    6.String                 char, varchar, longvarchar
         *    7.byte  array            binary,   varbinary
         *    8.java.sql.Date          Date
         *    9.java.sql.Time          Time
         *    10.java.sql.Timestamp    Timestamp
         */


public class QueryTest {

    @Test
    public void  QTest() {
        //当Java中自定义的类的属性名与数据库中的列名不一致时,可以在查询语句这里起(与自定义类属性名相同的)别名解决
        String Qsql = "select * from student where Sex = ? and Sage < ?";
        UserInfo [] Students = SelectQuery(Qsql, "1",100);
        for(UserInfo Stu:Students){
            if(Stu ==null) break;
            System.out.println(Stu);
        }


    }


    public static UserInfo[] SelectQuery(String QuerySQL, Object...args){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        UserInfo [] Students = new UserInfo[100];  //对象数组

        try {
            //建立数据库连接
            conn = GetConnection.getConnection();
            ps = conn.prepareStatement(QuerySQL);
            for( int i= 0 ; i < args.length ; ++i){
                ps.setObject(i+1,args[i]);
            }

             resultSet = ps.executeQuery();      //返回查询的结果集

            //获取结果集中,描述数据类型的元数据:ResultSetMetaData
            ResultSetMetaData rsmd = resultSet.getMetaData();
            //获取数据库中数据类型列数的多少
            int ColumnCount = rsmd.getColumnCount();
            System.out.println("该表有"+ ColumnCount + "列。");
            int index = 0 ;
            //处理结果集
            while(resultSet.next()){
                //判断结果集下一节点是否有数据,若有返回true,指针下移,没有就返回false
               //输出方法:  1.字符串拼接输出    2.Object [] data = new Object[] { Sno , Sname , Sex , Sage , InTime }
                // 3. 将数据封装为一个对象,一个对象代表数据库表的一条记录,对象的属性就是一条记录中的一个字段

                //创建一个自定义的UserInfo对象,通过两重循环来接收数据库查询返回的数据,要在while循环体里创建,
                // 避免在循环体外面浪费内存空间(查询不到对象时)
                UserInfo Student = new UserInfo();
                for(int j = 0 ; j < ColumnCount; ++j){
                    //通过resultSet,遍历一条记录(一个对象)中的所有字段(属性)
                    Object ColumnValue = resultSet.getObject(j+1);

                    //通过元数据的getColumnName(),获取当前遍历的字段名,即当前列名
                    //通过元数据的getColumnLabel(), 获取当前字段(列)的别名
                    String ColumnLabel = rsmd.getColumnLabel(j+1);

                    //给对象指定属性(列名) ColumnName,再给该属性赋值:ColumnValue,
                    //根据列名,用反射机制获取该列名在UserInfo类中的数据类型
                    Field field = UserInfo.class.getDeclaredField(ColumnLabel);

                     //如果field是public类型,则不用setAccessible(true),
                    // 给(带有当前列名的)数据类型的属性赋值,并设置为相应对象的属性
                    field.setAccessible(true);
                    field.set(Student,ColumnValue);
                }
                //给对象数组添加对象
               Students[index] = Student;
                index++;
            }

        }catch(SQLException e){
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        } catch(ClassNotFoundException e){
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally{
            try{
               GetConnection.CloseResource(conn,ps,resultSet);
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
        //返回接收结果集的对象
        return  Students;
    }
}

package PreparedStatementCURD;

import org.junit.Test;
import util.GetConnection;
import User.UserInfo;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @description  针对不同表的通用的查询操作(泛型,反射)
 * @author Vodka
 * @date 2021/07//17:25
 */
public class DifferentTableOperation {
    @Test
    public  void TableSQL(){
        String sql = "select * from student where sex = ?";
        List<UserInfo> Students = TableSearch(UserInfo.class,sql,"0");
        for(UserInfo obj :Students){
            System.out.println(obj);
        }
    }
    //使用泛型的通用表查询
    //    这个<T> T 可以传入任何类型的数据
//   * 关于参数T
//   * 第一个 表示是泛型
//   * 第二个 表示返回的是T类型的数据
//   * 第三个 限制参数类型为T
    public <T> List<T> TableSearch(Class<T> TableClass, 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 t = TableClass.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 = t.getClass().getDeclaredField(ColumnLabel);
                    field.setAccessible(true);  // 当要修改不是public的属性时,要设置为truee
                    field.set(t, ColumnValue);
                }
                //添加到表的集合对象中
                TList.add(t);

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


//操作类,包含两个方法,一个是通用查询,一个是增删改通用
package Instrument;

import User.CetStu;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Vodka
 * @date 2021/07//15:53
 */
public class Operation {
    //高内聚,低耦合,封装一个curd通用的函数,因为参数是不确定的,所以利用可变参数
    public static int Update(String sql,Object...args) {
        Connection conn = null;
        PreparedStatement ps = null;
        int ExecuteRS = 0;
        try {
            //建立连接
            conn = GetConnection.getConnection();
            //预编译
            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 {
                if (conn != null && ps != null) GetConnection.Close(conn, ps);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return ExecuteRS;
    }

    public static  <T> List<T> TableSearch(Class<CetStu> TableClass, 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 t = (T) TableClass.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 = t.getClass().getDeclaredField(ColumnLabel);
                    field.setAccessible(true);  // 当要修改不是public的属性时,要设置为truee
                    field.set(t, ColumnValue);
                }
                //添加到表的集合对象中
                TList.add(t);

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值