首页 > Java > java教程 > 正文

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

心靈之曲
发布: 2025-10-11 09:13:28
原创
480人浏览过

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:

BetterYeah AI
BetterYeah AI

基于企业知识库构建、训练AI Agent的智能体应用开发平台,赋能客服、营销、销售场景 -BetterYeah

BetterYeah AI 110
查看详情 BetterYeah AI
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: 禁止插入该字段,让数据库使用默认值。

注意事项:

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

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
    登录后复制
  2. updatable = false: 通常还需要设置 updatable = false,以防止在更新操作时覆盖数据库中的值。

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

总结

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

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

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号