表的字段名与类的属性名不相同的表数据的查询操作的封装 [JDBC][Java]

表的字段名与类的属性名不相同的表数据的查询操作的封装

我们在实际编程中:

对于在数据库中的字段名我们通常喜欢起名为order_id等等类似的样子,在数据库中我们对于字段名的起名一般都是全部字母小写,然后多个单词之间使用_(下划线)隔开

而对于java类中的属性名我们通常设置为orderId等等类似的样子,在java中我们对于属性名起名一般都是首字母小写,从第二个单词开始首字母大写

所以在实际编程中就很可能我们的数据库中的字段名和与对应的Java类中的属性名根本就不相同

  • 一旦我们的数据库中的字段名和对应的java类中的属性名不相同的时候,如果这个时候我们去使用反射给对应的java类的对象的该属性赋值的时候我们通常都是先获得该java类中的该属性对应的Field对象,但是我们要获得java类中的该属性对应的Field对象,那么我们就要使用对应的java类的运行时类的实例去调用getDeclaredField(String fieldname)方法去获得对应的java类中名为fieldname的属性的Field对象,但是这个时候我们不知道这Java类中的属性名是什么? 我们只能知道我们通过查询操作得到的结果集中的字段名(查询的结果集中的字段名我们可以通过结果集的元数据通过调用getcolumnName(int columnIndex)方法获得),但是这个时候我们的结果集中的字段名显然就是数据表中的字段名,这个时候又由于我们的数据表中的字段名和我们的java类中的属性名不相同,那么我们就不能获得Java类中名为getcloumnName()方法的返回值的Field对象
    • 所以如果我们还是使用以前的方式对这个问题进行查询的时候,这个时候就会报一个异常(运行时异常)NoSuchFieldException --> 这个异常的意思就是表示找不到对应的Field对象
      • 这个异常会在我们使用运行时类的对象调用getDeclaredField(String fieldname)方法的时候发生
    • 那么我们如何解决上面的问题?
      • 我们可不可以在执行的sql语句中加上列的别名(也就是给列起一个别名),让这个列的别名和我们java中的属性名相同,然后我们通过调用结果集元数据对象的getColumnName(int columnIndex)方法来获得对应的结果集中的列的别名?
        • 这个时候想法是对的,但是这个时候我们去执行这个程序发现还是会报错,同样还是会出现一个NoSuchFieldException
      • 那么我们要如何解决这个问题?(或者说到底是哪里出现了问题?)
        • 这里其实是因为我们使用结果集的元数据对象调用的方法有问题, 我们使用ResultSetMetadata接口实现类的对象调用getColumnName(String columnIndex)方法的功能时获得结果集中的对应索引位置的列名,而不是获得对应索引位置的列的别名,那么我们如何获得结果集中的列的别名?
          • 这里我们就要使用结果集的元数据对象调用getColumnLabel(String columnIndex)方法来获得结果集中对应索引位置的字段名 – > 其实这里我们就是使用getColumnLabel()方法代替了getColumnName()方法
这里我们给出具体代码:
  • 注意: 这里是针对于结果集中只有一条记录的情况实现的通用编程,并且这个时候在数据库中的数据表中的字段名和java类中的属性名是不相同的
package jdbc.针对返回一条记录的通用查询操作;

import com.ffyc.bean.Player;
import com.ffyc.util.JDBCUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class OneForQueryPlus {
    public static Player oneForQueryPlus(String sql,Object ...args) throws SQLException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {

        //获取数据库连接
        Connection conn = JDBCUtils.getConnection();

        //执行sql语句的预编译操作
        PreparedStatement ps = conn.prepareStatement(sql);

        //填充占位符
        for(int i = 0;i < args.length;i++){
            ps.setObject(i+1,args[i]);
        }

        //执行SQL语句,并且返回查询到的结果集
        ResultSet rs = ps.executeQuery();

        //使用结果集调用next()方法判断结果集中是否有数据
        if (rs.next()) {
            //创建Player类的对象用于承装数据
            Player p = new Player();

            //如果结果集中没有数据,那么也就不用创建结果集对应的元数据对象了
            ResultSetMetaData rsmd = rs.getMetaData();

            //使用结果集的元数据(ResultSetMetaData接口实现类的对象)获取修饰数据的一些数据(字段别名,字段数目)
            int columnCount = rsmd.getColumnCount();

            for(int i = 0;i < columnCount;i++) {
                //获取结果集中的字段名(通过结果集对应的元数据)
                String columnName = rsmd.getColumnLabel(i + 1);

                //获取结果集中对应索引位置的字段值
                Object columnValue = rs.getObject(i + 1);

                //通过Player类的运行时类的实例来获取对应的Player类中的声明为columnName的属性对应的Field对象
                Field field = Player.class.getDeclaredField(columnName);
                //由于Player类中的这个属性我们设置为了私有权限,在Player类之外无法操作,这个时候我们使用对应的Field对象
                //调用setAccessible()方法,在其中传入参数true,那么就能保证即使这个属性是私有属性,那么我们在Player类之外
                // 也可以对这个属性进行赋值操作
                field.setAccessible(true);
                //将对应查询出的数据值封装到我们创建的Player类的对象中
                field.set(p, columnValue);
            }
            return p;
        }
        return null;

    }
    //测试代码
    public static void main(String[] args) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, IOException {
        String sql = "\n" +
                "SELECT id,`name`,birthday brithday,high height,wei weight,play\n" +
                "FROM employees\n" +
                "WHERE id = ?";
        Player player = OneForQueryPlus.oneForQueryPlus(sql,5);
        System.out.println(player);
    }
}

我们将对应查找到的结果封装到了我们的自定义类Player中,下面我们给出Player类
package com.ffyc.bean;

import java.sql.Date;

/**
 * 用于接收nba数据库中的employees表中的数据的JavaBean
 */
public class Player {
    private int id;
    private String name;
    private Date brithday;
    private int height;
    private String play;
    private int teamId;
    private int weight;

    public Player(){

    }
    public Player(int id,String name,Date brithday,int height,String play,int teamId,int weight){

        this.id = id;
        this.name = name;
        this.brithday = brithday;
        this.play = play;
        this.teamId = teamId;
        this.weight = weight;

    }

    //get()和set()方法
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBrithday() {
        return brithday;
    }

    public void setBrithday(Date brithday) {
        this.brithday = brithday;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public String getPlay() {
        return play;
    }

    public void setPlay(String play) {
        this.play = play;
    }

    public int getTeamId() {
        return teamId;
    }

    public void setTeamId(int teamId) {
        this.teamId = teamId;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
    //重写的toString()方法

    @Override
    public String toString() {
        return "Player{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", brithday=" + brithday +
                ", height=" + height +
                ", play='" + play + '\'' +
                ", teamId=" + teamId +
                ", weight=" + weight +
                '}';
    }
}

总结:

针对于数据库中的数据表中声明的字段名和java中对应的类的属性名不相同的情况:

  1. 必须在声明sql时使用类的属性名来命名查询的段的别名
  2. 使用ResultSetMetaData接口实现类的对象获取结果集中的列的别名的时候要使用getColumnLabel(int columnIndex)方法来代替getColumnName(int columnIndex)方法

如果在SQL语句中没有使用列的别名,这个时候我们使用getColumnLabel(int columnIndex)方法获得到的就是列名

ResultSet接口实现类中封装了结果集的数据内容,而ResultSetMetaData接口实现类的对象表示的是结果集的元数据,而元数据就是对数据进行修饰的数据,所以我们的ResultSetMetaData接口实现类的对象中封装的应该是修饰结果集中数据的数据 ----> 那么什么是修饰结果集中的数据的数据?

  • 结果集中的数据是字段值,那么修饰字段值的当然就是字段名称,字段的数目等等
    • 所以我们想要获得结果集中的字段值的时候我们就要使用ResultSet去获得,而我们如果想要获得结果集中的字段的名称或者字段的数目的时候我们就要通过ResultSetMetaData接口的实现类的对象
declared 英文含义: 声明

补充:

列的别名是相对于什么来说的?是相对于实际的数据库中的数据表还是相对于虚拟表?

  • 是相对于虚拟表来说的,列的别名就是我们在查询操作中为结果集中的查询的列名起的一个别名,如果我们没有起别名这个时候查询的结果集中的列名默认就是和数据库中真实存在的数据表的列名相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值