Spring Data JPA 忽略数据库默认值问题及解决方案

spring data jpa 忽略数据库默认值问题及解决方案

本文旨在解决在使用 Spring Data JPA 时,数据库表字段的默认值被覆盖的问题。我们将探讨 JPA 默认行为,并提供使用 `@Generated` 注解来确保数据库默认值生效的解决方案。通过本文,你将了解如何在 Spring Data JPA 应用中正确处理数据库默认值,避免数据不一致的问题。

在使用 Spring Data JPA 进行数据库操作时,有时会遇到数据库表字段定义的默认值没有生效,而是被 JPA 覆盖的情况。这通常是因为 JPA 默认情况下会显式地插入所有列,从而忽略了数据库层面的默认值设置。本文将介绍如何解决这个问题,确保数据库默认值能够正确填充。

问题分析

当使用类似如下的 SQL 创建表时,CREATED_ON 和 CREATED_BY 列都定义了默认值:

CREATE TABLE CONFIGSERVER.PROPERTIES (    ID NUMBER GENERATED ALWAYS AS IDENTITY ( START WITH 1 CACHE 20 ) ,    APPLICATION VARCHAR2 (4000) ,    PROFILE     VARCHAR2 (4000) ,    LABEL       VARCHAR2 (4000) ,    PROP_KEY    VARCHAR2 (4000) NOT NULL,    VALUE       VARCHAR2 (4000) NOT NULL,    CREATED_ON  TIMESTAMP DEFAULT SYSDATE,    CREATED_BY  VARCHAR2 (100) DEFAULT COALESCE(        REGEXP_SUBSTR(SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER'),'^[^:]*'),        SYS_CONTEXT('USERENV','SESSION_USER')),    UPDATED_ON  TIMESTAMP ,    UPDATED_BY  VARCHAR2 (100)) LOGGING;

如果在不使用 JPA 的情况下,直接使用 SQL 插入数据,这些默认值会被正确填充。但如果使用 Spring Data JPA,则可能会发现 CREATED_ON 和 CREATED_BY 的默认值没有生效。

解决方案:使用 @Generated 注解

为了解决这个问题,可以使用 JPA 的 @Generated 注解。这个注解可以指示 JPA 在插入数据时,不要显式地插入该列,而是从数据库中读取该列的值。

修改实体类 Properties,在 createdOn 和 createdBy 字段上添加 @Generated 注解,并设置 insertable = false:

package com.example.configcrud.model;import javax.persistence.*;import java.sql.Timestamp;import org.hibernate.annotations.Generated;import org.hibernate.annotations.GenerationTime;@Entity@Table(name = "properties")public class Properties {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private long id;    @Column(name = "application")    private String application;    @Column(name = "profile")    private String profile;    @Column(name = "label")    private String label;    @Column(name = "prop_key")    private String propKey;    @Column(name = "value")    private String value;    @Generated(GenerationTime.INSERT)    @Column(name = "created_on", updatable = false, insertable = false)    private Timestamp createdOn;    @Generated(GenerationTime.INSERT)    @Column(name = "created_by", updatable = false, insertable = false)    private String createdBy;    public Properties(String application, String profile, String label, String propKey, String value) {         this.application = application;         this.profile = profile;         this.label = label;         this.propKey = propKey;         this.value = value;    }    public Properties() {    }    public String getApplication() {        return application;    }    public void setApplication(String application) {        this.application = application;    }    public String getProfile() {        return profile;    }    public void setProfile(String profile) {        this.profile = profile;    }    public String getLabel() {        return label;    }    public void setLabel(String label) {        this.label = label;    }    public String getPropKey() {        return propKey;    }    public void setPropKey(String propKey) {        this.propKey = propKey;    }    public String getValue() {        return value;    }    public void setValue(String value) {        this.value = value;    }    public Timestamp getCreatedOn() {        return createdOn;    }    public Timestamp setCreatedOn() {        return createdOn;    }    public String getCreatedBy() {        return createdBy;    }    public String setCreatedBy() {        return createdBy;    }    @Override    public String toString() {        return "Properties [id=" + id + ", " +                "application=" + application + ", " +                "profile=" + profile + ", " +                "label=" + label +                "propkey=" + propKey +                "value=" + value +                "CreatedOn=" + createdOn +                "CreatedBy=" + createdBy + "]";    }}

代码解释:

@Generated(GenerationTime.INSERT): 指定在插入时生成该字段的值。GenerationTime.INSERT 表示在插入时从数据库读取值。@Column(name = “created_on”, updatable = false, insertable = false):name = “created_on”: 指定数据库表中的列名。updatable = false: 禁止更新该字段。insertable = false: 禁止插入该字段,让数据库使用默认值。

注意事项:

依赖: 确保添加了 org.hibernate 的依赖,因为 @Generated 注解来自于 Hibernate。如果使用的是其他 JPA 实现,需要使用对应的注解。

    org.hibernate    hibernate-core

updatable = false: 通常还需要设置 updatable = false,以防止在更新操作时覆盖数据库中的值。

insertable = false: insertable = false 是关键,它告诉 JPA 不要尝试插入这个字段,从而允许数据库使用默认值。

总结

通过使用 @Generated 注解并设置 insertable = false,可以有效地解决 Spring Data JPA 覆盖数据库默认值的问题。这种方法确保了在插入数据时,数据库能够使用其自身定义的默认值,从而维护数据的一致性和准确性。在实际开发中,应该根据具体情况选择合适的策略来处理数据库默认值,避免潜在的数据问题。

以上就是Spring Data JPA 忽略数据库默认值问题及解决方案的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/22847.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月1日 21:28:02
下一篇 2025年11月1日 21:33:24

相关推荐

发表回复

登录后才能评论
关注微信