IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 表的字段名与类的属性名不相同的表数据的查询操作的封装 [JDBC][Java] -> 正文阅读

[大数据]表的字段名与类的属性名不相同的表数据的查询操作的封装 [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 英文含义: 声明

补充:

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

  • 是相对于虚拟表来说的,列的别名就是我们在查询操作中为结果集中的查询的列名起的一个别名,如果我们没有起别名这个时候查询的结果集中的列名默认就是和数据库中真实存在的数据表的列名相同
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:18:09  更:2022-04-04 12:20:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:23:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码