Java 使用 JDBC 查询数据库,表内字段类型为 bigint,在 java 中为啥变成 Long 了?

吼猴 · 2021年09月29日 · 最后由 陈恒捷 回复于 2021年09月30日 · 2969 次阅读

背景:准备通过 JDBC 查询数据库,然后将数据库内容转为实体类
问题现象:数据库字段属性为id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
,在 java 中 debug 发现类型变为 Long
不应该是 int 吗。。。

代码:

public static synchronized Object query(String sql, String tab) throws Exception {
        Class aClass = Class.forName("com.springbootdata.demo.dal.entity." + tab);
        List<Object> objects = new ArrayList<>();
        try {
            // 执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = getConnection().createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            //获取列相关信息
            ResultSetMetaData rsm = rs.getMetaData();
            while (rs.next()) {
                Object obj = aClass.newInstance();
                for (int i = 1; i < rsm.getColumnCount(); i++) {
                    System.out.println("列名:" + rsm.getColumnLabel(i) + "\t列值:" + rs.getObject(i));
                    String fieldName = "set" + StringUtils.capitalize(getName(rsm.getColumnLabel(i)));
                    Method method = null;
                    if (rs.getObject(i) instanceof BigInteger) {
                        method = obj.getClass().getMethod(fieldName, Long.class);
                        method.invoke(obj, ((BigInteger)rs.getObject(i)).longValue());
                    } else if (rs.getObject(i) instanceof Timestamp) {
                        method = obj.getClass().getMethod(fieldName, java.util.Date.class);
                        method.invoke(obj, new java.util.Date(((Timestamp)rs.getObject(i)).getTime()));
                    } else if (rs.getObject(i) instanceof java.sql.Date) {
                        method = obj.getClass().getMethod(fieldName, java.util.Date.class);
                        method.invoke(obj, new java.util.Date(((java.sql.Date)rs.getObject(i)).getTime()));
                    } else {
                        method = obj.getClass().getMethod(fieldName, rs.getObject(i).getClass());
                        method.invoke(obj, rs.getObject(i));
                    }
                }
                objects.add(obj);
            }
            close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            close();
        }
        return objects;
    }
共收到 5 条回复 时间 点赞

jdbc 里面默认 bigint 就会转 Long ,官方文档:
https://docs.oracle.com/cd/E19830-01/819-4721/beajw/index.html

PS:如果你用的是 spring ,强烈推荐用 https://github.com/davidfantasy/mybatis-plus-generator-ui 来自动生成所有数据库表的实体类 + 增删改查接口逻辑。省力且避免手写代码出错,比你这么手写要简便高效很多。

Java 的用 mybatis 比较好吧···

mysql 和 java 的 int 范围都是-2147483648~ 2147483648,要兼容更大的数字用 bigint,那 java 里面还用 int 怎么转换?超过 2147483648 都算啥呢?

陈恒捷 回复

明白了,谢谢大佬
选择手写的原因是为了解决接口自动化中需要维护大量的实体类的问题(一旦线上表结构有更新自动化的实体类也要跟着改),准备在查询后生成一个实体类,目前的方案如下,不知道 github 上有现成的轮子用不,写起来有点费劲。。。

public static synchronized Object query(String sql) throws SQLException {
        Map<String, Object> map = new HashMap<>();
        List<Object> objects = new ArrayList<>();
        try {
            // 执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = getConnection().createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            //获取列相关信息
            ResultSetMetaData rsm = rs.getMetaData();
            for (int i = 1; i <= rsm.getColumnCount(); i++) {
                String fieldName = rsm.getColumnName(i);//获取列名
                int type = rsm.getColumnType(i);//获取数据库中该列的数据类型的type
                logger.debug("\t列名" + fieldName + "\t列类型:" + rsm.getColumnTypeName(i) + "\t是否可为null:"
                        + rsm.isNullable(i) + "\t枚举" + type );
                Class<?> aClass = JDBCUtil.getJavaType(type);//通过type获取对应的Java类型
                map.put(getName(fieldName), aClass);
            }

            while (rs.next()) {
                CglibCreateUtil createUtil = new CglibCreateUtil(map);
                for (int i = 1; i <= rsm.getColumnCount(); i++) {
                    String fieldName = getName(rsm.getColumnName(i));//将字段名转为驼峰式命名
                    Object value = rs.getObject(i);//获取字段的值
//                    System.out.println("列名:" + fieldName + "\t列值:" + value);
                    createUtil.setBeanMapValue(fieldName, value);
                }
                Object obj = createUtil.getObj();
                objects.add(obj);
            }
            close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            close();
        }
        return objects;
    }
吼猴 回复

查询后把内容变为实体类对象,这个就是 mybatis 做的事情了。你可以试试引入 Mybatis ?实体类自动生成这些 我前面说的这个工具都有。

另外,不知道你这里的查询条件有多少,我们以前接口测试查数据,可能更倾向于直接写 sql ,通过 where 条件限定内容,比较灵活。如果查出来的结果有比较多需要校验的,那就通过外部表格等方式来记录,甚至进一步通过自动写入表格来自动生成断言。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册