
本文旨在解决在使用 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 + "]";
}
}代码解释:
注意事项:
依赖: 确保添加了 org.hibernate 的依赖,因为 @Generated 注解来自于 Hibernate。如果使用的是其他 JPA 实现,需要使用对应的注解。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>updatable = false: 通常还需要设置 updatable = false,以防止在更新操作时覆盖数据库中的值。
insertable = false: insertable = false 是关键,它告诉 JPA 不要尝试插入这个字段,从而允许数据库使用默认值。
总结
通过使用 @Generated 注解并设置 insertable = false,可以有效地解决 Spring Data JPA 覆盖数据库默认值的问题。这种方法确保了在插入数据时,数据库能够使用其自身定义的默认值,从而维护数据的一致性和准确性。在实际开发中,应该根据具体情况选择合适的策略来处理数据库默认值,避免潜在的数据问题。
以上就是Spring Data JPA 忽略数据库默认值问题及解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号