公司的ORM用的是Spring Data JPA,前东家用的是mybatis,上一家公司的代码规范特地嘱咐了,实体类使用包装类,不要使用基础数据类型。于是引发了小小疑问,ORM的实体类到底应该使用什么类型才是对的。
包装类和基础类的差别
1.包装类和基本数据类型最大的区别在于,包装类是一个对象,但是基础数据类型只有一个值。也就是说,包装类在堆内存是有一块地方分配内存空间的,但是基础数据类型的值仅存在栈内存。
2.包装类可以为null,但是基础类型不能为null。
int a; // 即使不给字面量,也会有默认值0
Integer b; // 因为没有实例化对象,所以b为null
记住这个差别,这个差别是实体类选型重要参考原因!!!
为什么要有包装类
包装类的出现,个人感觉是因为泛型必须传一个Object。List<E>,如果只有基础数据类型,泛型的使用会非常受限制。至于泛型为什么一定要传Object,有时间会继续整理专门说。
JDK在我们看不见的地方,帮我们做着装箱和拆箱的事情。
// 自动装箱
List<Integer> numList = new ArrayList<Integer>();
numList.add(1); // 这个时候,其实是numList.add(Integer.valueOf(1));
// 自动拆箱
Integer a = new Integer(3);
if(a==3){ // 首先a.intValue()l;自动拆箱成基础类型,然后和3比较字面量的值是否相等
....
}
一个技术数据类型和包装类比较==
的时候,会自动拆箱比较值,但是如果是包装类和包装类比较,例如:new Integer(200)==new Integer(200)?,比较的是内存地址
,所以两个包装类判断是否相等一定需要使用equals。
实体类数据类型选择策略
1.当某个值一定不为null时,可以使用基本数据类型,例如:状态标志位,分类标志位,只要有这条数据就这个字段值就一定有值,并且需要传给前端。
因为如果Entity类中使用了基础数据类型private int number;但是数据库为null的时候,如果返回了一个null,接口会报500,Null value was assigned to a property.
所以在使用的时候一定要注意。
2.JpaBuilder的Specification底层有一个Root泛型接口,刚才提到过,但凡涉及到泛型,包装类的性能绝对是好过基本数据类型,即使JDK会做自动拆箱和装箱,也绝对不可能为null。
因此,在后续的扩展中,如果专门对null值有处理或者约定的话,基本数据类型都是无法做到的。
MybatisPlus的QueryWrapper也有这个问题,而且QueryWrapper对null的封装更加完善,不能传null会带来很多问题。
综上所述,如果没有要求,优先选择包装类。
要求数据永远不为空时,有两种解决方案
(1)可以在建表时就添加约束,
CREATE TABLE `onetable` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '主键id',
`node` bigint(20) DEFAULT 0 not null COMMENT '车辆品牌',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC;
(2)Entity类直接赋初始值:
@Data
public class Entity(){
...
private Integer number = 0;
...
}