欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

bigint 有无符号对应java的Long和BigInteger

程序员文章站 2024-03-25 08:48:22
...

bigint 有无符号对应java的Long和BigInteger

这个问题是在实际工作中遇到的,是一个小的问题,但是如果不注意的话,造成的后续问题是比较严重的。下面就来重现一下这个问题。

首先我们先创建一张数据表,名为t_order. 位于test库中。

bigint 有无符号对应java的Long和BigInteger

CREATE TABLE `t_order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `tid` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

SQL语句如上,字段tid上是正常的bigint 类型,无其他限制条件。

下面使用SpringBoot+Mybatis来测试数据查询单独tid列。

bigint 有无符号对应java的Long和BigInteger

通过Debug可以看到allTids的数据是Long类型的。下面我们将数据库表修改一下。

CREATE TABLE `t_order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `tid` bigint(20) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

此时表的SQL如上,即在tid列上加上了无符号限制。我们重新运行测试代码:

bigint 有无符号对应java的Long和BigInteger

测试结果如上,可以看出,测试的tid类型就变成了BigInteger类型。当然在我们的控制台直接输出是不会出现问题的,但是将测试代码换成下面的:

bigint 有无符号对应java的Long和BigInteger

通过测试结果可以看出,无法将相应的Long类型的数据剔除掉。

当然,这个问题如果在Mybatis中使用泛型限制的话,也不会出现自动映射为BigInteger的情况。

public interface OrderMapper {
    List findAllTids();
    List<Long> findAllLongTids();
    List<Map<String,Object>> findAll();
}

bigint 有无符号对应java的Long和BigInteger

通过上面的截图可以看出,由于查询的时候使用了泛型进行相应的类型限制,可以看出即使在数据库表中设置了tid的类型为无符号,也可以自动转为Long类型。这种情况下是不会出现问题的。

但是公司的DAO层比较多样化,有一部分DAO层是基于apache的DBUtils进行封装的,对于切换数据源比较方便,所以使用时偏向于这个,但是在查询单列的id时,遇到了上述情况,加了泛型也是无法转换,我进入源码并且看到这样一段代码:

public abstract class AbstractListHandler<T> implements ResultSetHandler<List<T>> {
    public AbstractListHandler() {}
    public List<T> handle(ResultSet rs) throws SQLException {
        ArrayList rows = new ArrayList();
        while(rs.next()) {
            rows.add(this.handleRow(rs));
        }
        return rows;
    }
    protected abstract T handleRow(ResultSet var1) throws SQLException;
}
// 单列的数据处理
public class ColumnListHandler<T> extends AbstractListHandler<T> {}

可以看出,在DBUtilsAbstractListHandler类中,在处理时,并没有进行类型限制,只是在方法声明的地方添加了T,其实没什么用,查询出来该是BigInteger还是这个,不会自动转为泛型设置的类型。(这里是个坑),但是使用Mybatis可以避免了。

说明:如果是有符号的 Bigint(20) 取值范围是-9223372036854775808~9223372036854775807,与 Java中的java.lang.Long的取值范围是一致的,而如果是无符号的Bigint(20),其取值范围是0 ~ 18446744073709551615,其中一般超出了Long的取值范围,会被映射为BigInteger。

相关标签: 踩坑