即使没有任何变化,Spring Auditable 实体也会被修改

Posted

技术标签:

【中文标题】即使没有任何变化,Spring Auditable 实体也会被修改【英文标题】:Spring Auditable entity is being modified even when nothing has changed 【发布时间】:2015-02-16 09:12:40 【问题描述】:

注意:这是一个复杂的问题,所以我希望我已经涵盖了相关部分。如果没有,我将根据要求编辑并添加更多信息。

我们使用 Spring (4.1.0) 和 Hibernate (4.3.6),并且我们定义了一个基类,我们的所有实体都扩展名为 BaseAuditableEntity(代码如下)。当在 @Transactional 方法中加载任何实体,然后对其进行修改和保存时,该实体的 modified_by_user_idmodified_ts 都将使用登录用户的 ID 进行更新,并执行正在进行的任何更改。

我们的问题是,每当在这些@Transactional 方法之一中加载AppUser(也扩展了BaseAuditableEntity)时,它也会看到modified_by_user_idmodified_ts 被设置,即使它还没有被设置修改的。这会产生一个问题,因为当我们不需要时,几乎每个请求都会写入我们的用户表。请注意,这也可能会影响 @Transactional 不显式加载 AppUser 的方法,因为 AuditorBean 会加载 AppUser 本身。

我假设这与 AppUser 实体是 BaseAuditableEntity 本身的一部分这一事实有关。有人可以证实这一点吗?有没有办法解决这个问题?

我们的 BaseAuditableEntity 类,包括 AppUser 在内的每个实体都扩展:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseAuditableEntity implements Auditable<AppUser, Long> 

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hibernate_sequence")
    @SequenceGenerator(name = "hibernate_sequence", sequenceName = "blah_sequence", allocationSize = 1)
    @Column(name = "id")
    private Long id;

    @CreatedBy
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "created_by_user_id")
    private AppUser createdBy;

    @LastModifiedBy
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "modified_by_user_id")
    private AppUser lastModifiedBy;

    @Column(name = "created_ts")
    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    @Column(name = "modified_ts")
    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;

    // ...

我们的JpaConfig

@Configuration
@EnableJpaRepositories(basePackages = 
        "blah.blah.blah")
@ComponentScan(basePackageClasses = AuditorBean.class)
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "auditorBean")
public class JpaConfig extends BaseConfig 

    // ...


还有我们的AuditorBean

@Component
public class AuditorBean implements AuditorAware<AppUser> 

    @Override
    public AppUser getCurrentAuditor() 
        // omitting some code that finds a user. I think the only relevant thing here
        // is that we're using the repo to find the user by ID and not using an
        // entity that's already been loaded
        return userRepository.findOne(id);
    


【问题讨论】:

【参考方案1】:

我的建议是保持审计简单和定义

@CreatedBy
private Long createdBy;

没有实际关联,只存储 AppUser 的 ID。

@组件 公共类 AuditorBean 实现 AuditorAware

@Override
public Long getCurrentAuditor() 
    // .... find out the id
    return id;

【讨论】:

以上是关于即使没有任何变化,Spring Auditable 实体也会被修改的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使源代码没有变化,Gradle 的“构建”任务也不是最新的?

RestKit 强制 CoreData 保存

如果表格有任何变化,我需要倾听,如果有变化,请启用/禁用“保存”按钮 |角

即使设备没有移动,位置也会不断变化

即使没有变化也能发出流量

即使 JPA 实体不脏,我是不是可以强制 spring-data 更新可审计字段?