休眠:@Columnupdatable = false不适用于@MappedSuperclass

问题描述

我正在将Spring Data JPA与Hibernate一起使用,并且在@Column批注上使用updatable = false属性时遇到了麻烦。

我的所有@Entity对象都有一个基类,其createdDate定义如下:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Setter
@Getter
@ToString
public abstract class BaseEntity {

    @CreatedBy
    @Column(name = "CREATE_USER_ID",nullable = false,updatable = false)
    protected String createdBy;

    @CreationTimestamp
    @Column(name = "CREATE_TS",columnDefinition = "TIMESTAMP WITH TIME ZONE",updatable = false)
    protected Instant createdDate; //Audit for data use replication conflict resolution (Oracle Golden Gate)

    @LastModifiedBy
    @Column(name = "LAST_UPDATE_USER_ID")
    protected String lastModifiedBy;

    @UpdateTimestamp
    @Column(name = "LAST_UPDATE_TS",columnDefinition = "TIMESTAMP WITH TIME ZONE")
    protected Instant lastModifiedDate;

以下是我的子实体

@Entity
@Table(name = "CUSTOMER")
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = {""})
public class Customer extends BaseEntity 

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "CUSTOMER_ID_SEQ")
    @SequenceGenerator(sequenceName = "Customer_ID_SEQ",allocationSize = 1,name = "CUSTOMER_ID_SEQ")
    @Column(name = "CUSTOMER_ID")
    private Long CustomerId;             //Primary identifier
    @Column(name = "CUSTOMER_NAME")
    private String customerName;        //Customer Name
    @Column(name = "COUNTRY")
    private String customerCountry;     //Customer Country
    @Column(name = "REGION")
    private String customerRegion;      //Customer Region

}

CustomerService.java中的代码段

public CustomerDetails updateCustomer(CustomerDetails customerDetails,Long customerId) {
        Customer customer = customerEntityToDTOMapper.dtoToEntity(customerDetails);
        /**
            Some sort of business logic
        **/
        Customer updatedCustomer = customerRepository.saveAndFlush(customer);
        return customerEntityToDTOMapper.entityToDTO(updatedCustomer);
    }

现在,当我从邮递员调用updateCustomer API时,如果我更改了请求正文中的createdDate的值,它将在数据库中进行更新(数据库将用在请求正文中传递的新值替换createdDate的实际值)。理想情况下,这应该不会发生。无论我在requestBody中传递什么有效值,都不应在updateCustomer API调用中使用数据库中的createdDate。

同样在createCustomer请求中,如果createdDate = null,JPA将根据期望设置createdDate,并且我在repository.saveAndFlush()方法的响应中收到正确的日期。但是在updateCustomer中,如果我在实体中设置了createdDate = null,那么createdDate在repository.saveAndFlush()方法的响应中为null,即使它存在于数据库中。

有人可以帮助我解决我的问题吗?

解决方法

处理@Column批注属性以创建/更新/验证架构等,并从实体定义表上的约束(取决于hbm2ddl.auto属性)。

现在insertable使用updatable@persistenceContext发出查询,如果未显式提供查询并将其设置为false,它将忽略其查询中的字段。

由于您的情况尚未提供代码,而是如何设置值,因此我假设在update的情况下,您将createdDate设置为null,因为您将其设置为无效已将字段定义为

 @CreationTimestamp // This will add the timestamp if null when entity is new only
    @Column(name = "CREATE_TS",columnDefinition = "TIMESTAMP WITH TIME ZONE",nullable = false,updatable = false)
    protected Instant createdDate; 

因此,您的更新将createdDate显式更新为null,这将覆盖updatable=false和AFAIK,而updatable=false有一些奇怪的行为,它在实体中返回null(当您提取时保存后),然后再次保存实体时,会保留null值(无论updatable = false都会保存该值,因为hibernate会看到该值更改为null)

我建议删除updatable=false并仅使用@CreationTimeStamp属性,这将不会更新值See this,并且数据库约束应该存在以防止null >

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...