@Entity @Table(name = "tb_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private Boolean deleteFlag; private Boolean activeFlag; public User() { } }
如上实体类代码,两个布尔值的数据库字段是设置了默认值 0 的,在新增保存时,如果没设置两个属性的值,插入后并不能得到数据库的默认值,即仍然是 null 。
目前想到的办法有两个:
在实体属性上面加注解:@Generated(GenerationTime.INSERT)
加这个注解后,JPA 在插入数据库后,会执行一次 select 查询把相关字段的值查询回来,然后赋值给对象。
在实体属性上加上默认值,如 private Boolean deleteFlag = false
这种方法在阿里手册里不推荐,然而手册上面举的反例是时间字段,思考好久感觉并没有什么不妥的地方?
综上,不知道有没有更好的解决方案?
![]() | 1 Oktfolio 2021-01-07 12:10:09 +08:00 |
![]() | 2 wangyanrui 2021-01-07 12:14:24 +08:00 via Android 为什么要相信阿里手册 |
![]() | 3 Oktfolio 2021-01-07 12:18:54 +08:00 @wangyanrui 实际确实不应该这么做。 |
![]() | 5 wangyanrui 2021-01-07 12:25:19 +08:00 via Android @Oktfolio 为什么不应该这么做 |
![]() | 6 967182 2021-01-07 12:54:34 +08:00 boolean |
![]() | 7 Oktfolio 2021-01-07 13:59:50 +08:00 @NULL2020 可以啊,怎么不行?我只给一个字段赋了值,Hibernate SQL 执行日志是 insert into table_name (field) values (?)。 |
![]() | 8 zoharSoul 2021-01-07 14:06:34 +08:00 @wangyanrui 因为很奇怪 |
![]() | 9 Oktfolio 2021-01-07 14:06:54 +08:00 @wangyanrui 如果只是逻辑删除字段默认给 false 的话,问题不大。但是如果是别的字段,你又使用 DO 去做查询的话就会有坑,特别是时间,除非你再赋值为 null 。 |
![]() | 12 Oktfolio 2021-01-07 14:23:40 +08:00 @NULL2020 entityManager.clear(); 再根据 save 返回的 id 查询出来。但是你也得加上这个注解插入到数据库的才不会为 null 。 |
![]() | 14 wangyanrui 2021-01-07 15:24:54 +08:00 via Android |
15 ccccccccw 2021-01-07 15:38:56 +08:00 @wangyanrui new 一个空的对象作为查询条件的时候,本来 Boolean 的默认值是 null,jpa 就不会把他作为条件添加到 sql 中,但是如果设置了 false,jpa 就会将 false 添加到查询条件中 |
16 ccccccccw 2021-01-07 15:39:55 +08:00 @wangyanrui 也就是说,where deleteFlag = false |
![]() | 17 aragakiyuii 2021-01-07 15:42:06 +08:00 via iPhone @wangyanrui 如果用 Example 这种方式去查那得注意一下,不处理的话会默认当成查询条件 |
![]() | 18 aragakiyuii 2021-01-07 15:43:52 +08:00 via iPhone 这种我习惯把字段=默认值语句写在有参构造函数里 |
![]() | 19 ApmI00 2021-01-07 16:14:12 +08:00 所以,与其等插入后再查回,影响性能,不如在保存对象前,手动设置这两个字段,这样也不违反手册,就是代码嗦了一点。。。至于时间字段,怕是得用 @DynamicUpdate 配合建表 sql 了吧!!!不知道理解的可对 |
20 DeepUse 2021-01-07 16:21:50 +08:00 @Data @ToString @MappedSuperclass @EqualsAndHashCode public class BaseEntity { @Column(name = "create_time") @Temporal(TemporalType.TIMESTAMP) private Date createTime; @Column(name = "update_time") @Temporal(TemporalType.TIMESTAMP) private Date updateTime; @PrePersist protected void prePersist() { Date now = DateUtils.now(); if (createTime == null) { createTime = now; } if (updateTime == null) { updateTime = now; } } @PreUpdate protected void preUpdate() { updateTime = new Date(); } @PreRemove protected void preRemove() { updateTime = new Date(); } } |
![]() | 21 xuanbg 2021-01-07 16:34:06 +08:00 我一般在 get 方法里面这样写。但得注意需要正常返回 null 的字段可别也这样干。 pubic Boolean getDeleteFlag(){ return deleteFlag == null ? false : deleteFlag; } |
22 472690980 2021-01-07 16:41:05 +08:00 @Column(columnDefinition = "Integer default 0") private Integer accessFailedCount; 可以设置字段默认值,或者你直接用小写的 bool 不就完事了 默认就是 false |
![]() | 23 NULL2020 OP |
![]() | 24 wangyanrui 2021-01-07 18:34:16 +08:00 via Android |
![]() | 25 wangyanrui 2021-01-07 18:36:38 +08:00 |
26 472690980 2021-01-08 08:30:46 +08:00 小写的 bool 不就完事了吗,说明你这个字段是不可空的 |
27 zhenjiachen 2021-01-08 13:40:41 +08:00 阿里不推荐属性默认值?那 kotlin 的 data class 全是默认值,那是 kotlin 错了? |