Jpa 插入时如何同步数据库字段的默认值

2021-01-07 11:33:36 +08:00
 NULL2020
@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 。

目前想到的办法有两个:

  1. 在实体属性上面加注解:@Generated(GenerationTime.INSERT)

    加这个注解后,JPA 在插入数据库后,会执行一次 select 查询把相关字段的值查询回来,然后赋值给对象。

  2. 在实体属性上加上默认值,如 private Boolean deleteFlag = false

    这种方法在阿里手册里不推荐,然而手册上面举的反例是时间字段,思考好久感觉并没有什么不妥的地方?

综上,不知道有没有更好的解决方案?

2721 次点击
所在节点    Java
27 条回复
Oktfolio
2021-01-07 12:10:09 +08:00
wangyanrui
2021-01-07 12:14:24 +08:00
为什么要相信阿里手册😂
Oktfolio
2021-01-07 12:18:54 +08:00
@wangyanrui 实际确实不应该这么做。
NULL2020
2021-01-07 12:19:17 +08:00
@Oktfolio #1 这两个注解并不能解决该问题
wangyanrui
2021-01-07 12:25:19 +08:00
@Oktfolio 😂为什么不应该这么做
967182
2021-01-07 12:54:34 +08:00
boolean
Oktfolio
2021-01-07 13:59:50 +08:00
@NULL2020 可以啊,怎么不行?我只给一个字段赋了值,Hibernate SQL 执行日志是 insert into table_name (field) values (?)。
zoharSoul
2021-01-07 14:06:34 +08:00
@wangyanrui 因为很奇怪
Oktfolio
2021-01-07 14:06:54 +08:00
@wangyanrui 如果只是逻辑删除字段默认给 false 的话,问题不大。但是如果是别的字段,你又使用 DO 去做查询的话就会有坑,特别是时间,除非你再赋值为 null 。
NULL2020
2021-01-07 14:20:20 +08:00
@Oktfolio #7 我的问题是要把实体里没设置值的字段,在插入后把数据库自动生成的默认值带回来。
NULL2020
2021-01-07 14:21:16 +08:00
@967182 #6 实体类还是要用包装类型的,不然查询返回是空的话,就会报错了
Oktfolio
2021-01-07 14:23:40 +08:00
@NULL2020 entityManager.clear(); 再根据 save 返回的 id 查询出来。但是你也得加上这个注解插入到数据库的才不会为 null 。
NULL2020
2021-01-07 14:30:42 +08:00
@Oktfolio #12 所以最终还是得查一遍
wangyanrui
2021-01-07 15:24:54 +08:00
@zoharSoul
@Oktfolio
还是没 GET 到哪里奇怪,数据库默认 false,代码也默认 false,一个标志位,蛮合适的呀
ccccccccw
2021-01-07 15:38:56 +08:00
@wangyanrui new 一个空的对象作为查询条件的时候,本来 Boolean 的默认值是 null,jpa 就不会把他作为条件添加到 sql 中,但是如果设置了 false,jpa 就会将 false 添加到查询条件中
ccccccccw
2021-01-07 15:39:55 +08:00
@wangyanrui 也就是说,where deleteFlag = false
aragakiyuii
2021-01-07 15:42:06 +08:00
@wangyanrui 如果用 Example 这种方式去查那得注意一下,不处理的话会默认当成查询条件
aragakiyuii
2021-01-07 15:43:52 +08:00
这种我习惯把字段=默认值语句写在有参构造函数里
ApmI00
2021-01-07 16:14:12 +08:00
所以,与其等插入后再查回,影响性能,不如在保存对象前,手动设置这两个字段,这样也不违反手册,就是代码啰嗦了一点。。。至于时间字段,怕是得用 @DynamicUpdate 配合建表 sql 了吧!!!不知道理解的可对
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();
}

}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/742484

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX