手写Mybatis源码01


前言

这篇介绍怎么动态获取结果集中的数据并通过反射一一对应赋值给实体类,如果为空,则赋值null


一、定义一个Sql数据类型转换为java数据类型的工具类

首先我们先定义一个sql数据类型转换成java数据类型的工具类,后面我们会用到。

package com.darkForest.uitl;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.sql.*;

/*
* sql数据类型转换工具类
* */
@Slf4j(topic = "e")
public class SqlTypeUtil {
    public Class<?> sqlTypeToJavaType(String sqlType) throws SQLException {
        //我们使用反射来获得实体类的方法对象,通过方法对象调用invoke()方法来给实体类赋值,
        // 所以我们在工具类定义并返回数据类型的Class对象
        Class<?> javaType=null;
        switch (sqlType){
            case "VARCHAR":
            case "CHAR":
            case "TEXT":
                //返回String类型的Class对象
                javaType=String.class;
                 break;
            case "INT":
            case "SMALLINT":
            case "TINYINT":
                //返回int类型的Class对象
                javaType=int.class;
                break;
            case "DECIMAL":
                //返回BigDecimal类型的Class对象
                javaType= BigDecimal.class;
                break;
            case "DATE":
                //返回Date类型的Class对象
                javaType= Date.class;
                break;
            case "TIME":
                //返回Time类型的Class对象
                javaType= Time.class;
                break;
            case "TIMESTAMP":
                //返回Timestamp类型的Class对象
                javaType= Timestamp.class;
                break;
            case "BOOLEAN":
                //返回boolean类型的Class对象
                javaType= Boolean.class;
                break;
            default:
             log.debug("result:{}","未知类型");
                break;
        }
        return javaType;
    }
}


二、动态获取列对应的值并通过方法赋值给实体类

package com.darkForest.uitl;

import com.darkForest.entity.StudentUser;
import lombok.val;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;

//处理结果集工具类
public class ResultSetUtil {

    ResultSet resultSet;
    public ResultSetUtil(ResultSet resultSet){
        this.resultSet=resultSet;
    }
    public <T>T getEntity(Class clazz) throws InstantiationException, IllegalAccessException, SQLException, NoSuchMethodException, InvocationTargetException {
        //定义list集合存放实体类对象(避免数据库有多条记录的情况)
        List<Object> list=null;
        while (resultSet.next()) {
            //使用反射来通过无参构造函数来new一个实体类对象
            Constructor<?> constructor=clazz.getDeclaredConstructor();
            Object object=constructor.newInstance();
            //获取了结果集的元数据信息。结果集中列的信息,比如列的名称、数据类型、列的数量  getMetaData:得到(元数据对象)
            ResultSetMetaData md = resultSet.getMetaData();
            //得到结果集数据记录(列)数
            int columnCount = md.getColumnCount();
            for (int i = 1; i <=columnCount; i++) {
                //得到当前(i)对应的一条记录对象
                Object val=resultSet.getObject(i);
                //获取与查询结果集中指定列(对应的i)关联的目录名称
                String catalogName = md.getCatalogName(i);
                //得到当前列对应的值
                Object value=resultSet.getObject(i);
                //得到当前列的列名
                String name= md.getColumnName(i);
                //转换成方法名,对列名第一个字符做大写处理,与set拼接
                String firstStr=name.substring(0,1);
                String entityName="set"+firstStr.toUpperCase()+name.substring(1);
                //得到当前列的数据类型(这里要用到我们刚刚定义的工具类)
                String typeName=md.getColumnTypeName(i);
                Class<?> typeObject= new SqlTypeUtil().sqlTypeToJavaType(typeName);
                //得到实体类中对应的方法对象,并执行invoke方法
                Method method=clazz.getDeclaredMethod(entityName,typeObject);
                method.invoke(object,value);
            }
            list.add(object);
        }
        return (T)list;
    }
}

这种方式固然可以解决了一些问题,但是还是有一些弊端,比如,查询的不是数据库表中所有列的数据,而是其中的一些,那么在数据类型为String的情况下,没有查询的列对应的实体类中的属性的值是一个空串,而不是null,int的情况下,是默认值0,也不是null,这对于我们后面通过该实体类或集合做处理时很不方便,如何解决这个问题,下次我们继续讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值