Jpa 插入时如何同步数据库字段的默认值 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NULL2020
V2EX    Java

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

  •  
  •   NULL2020 2021-01-07 11:33:36 +08:00 3072 次点击
    这是一个创建于 1745 天前的主题,其中的信息可能已经有所发展或是发生改变。
    @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

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

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

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

    }
    xuanbg
        21
    xuanbg  
       2021-01-07 16:34:06 +08:00
    我一般在 get 方法里面这样写。但得注意需要正常返回 null 的字段可别也这样干。
    pubic Boolean getDeleteFlag(){
    return deleteFlag == null ? false : deleteFlag;
    }
    472690980
        22
    472690980  
       2021-01-07 16:41:05 +08:00
    @Column(columnDefinition = "Integer default 0")
    private Integer accessFailedCount;

    可以设置字段默认值,或者你直接用小写的 bool 不就完事了 默认就是 false
    NULL2020
        23
    NULL2020  
    OP
       2021-01-07 17:32:48 +08:00
    @472690980 #22 实测无用,我需要的是保存前未设置属性值,保存后能返回对应字段里数据库的默认值。

    综上,应该是只能保存前想办法设置默认值,或者保存后再执行一次查询操作。
    wangyanrui
        24
    wangyanrui  
       2021-01-07 18:34:16 +08:00 via Android
    @ccccccccw
    可能意思没表达正确,保存时工厂方法构造对象的时候,默认设置 WWIfalse,不是直接字段值为 false.
    哈哈哈,尴尬了
    wangyanrui
        25
    wangyanrui  
       2021-01-07 18:36:38 +08:00
    @ccccccccw
    可能意思没表达正确,保存时工厂方法构造对象的时候,默认设置为 false,不是直接字段值为 false.
    哈哈哈,尴尬了
    472690980
        26
    472690980  
       2021-01-08 08:30:46 +08:00
    小写的 bool 不就完事了吗,说明你这个字段是不可空的
    zhenjiachen
        27
    zhenjiachen  
       2021-01-08 13:40:41 +08:00
    阿里不推荐属性默认值?那 kotlin 的 data class 全是默认值,那是 kotlin 错了?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1291 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 17:18 PVG 01:18 LAX 10:18 JFK 13:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86