1

我有几个 JPA 实体,每个实体都有一个数据库用户列,在该列中我必须存储对表中特定行进行更改的用户。

我创建了一个'MappedSuperclass' Bean,所有实体都将从中扩展,这就是 MappedSuperclass。

@MappedSuperclass
public abstract class AuditableBean {

    @Column(name = "modifier_user", nullable = false)
    private String modifier_user;

    // Getters and Setters
}

这是一个从“MappedSuperclass”扩展而来的实体。

@Entity
@Table(name = "nm_area_ref")
public class ServingAreaReferenceBean extends AuditableBean {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "nm_area_ref_id")
    private UUID id;

    @Column(name = "nm_srv_area_desc", nullable = false)
    private String description;

    @Column(name = "nm_retired", nullable = false)
    private boolean retired;

    // Getters and Setters
}

并且,所有的 Bean 都有一个对应的服务方法,用于将数据保存在数据库中,这是服务类之一(每个服务注入一个用于 CRUD 操作的存储库)。

// Service
@Component
public class ServingAreaReferenceBO {

    @Inject private ServingAreaReferenceRepository repository; //repository injection
    @Inject private CloudContextProvider cloudContextProvider;

    public List<ServingAreaReferenceBean> getAllServingAreaReferences() {
        return Lists.newArrayList(repository.findAll());
    }

    public Optional<ServingAreaReferenceBean> findById(UUID id) {
        return repository.findById(id);
    }

    public ServingAreaReferenceBean create(ServingAreaReferenceBean servingAreaReference) {
        Optional<CloudContext> cloudContext = Optional.ofNullable(cloudContextProvider.get());// line 1
        servingAreaReference.setUpdaterUser(cloudContext.map(CloudContext::getUserId).orElse(null));// line 2
        return repository.save(servingAreaReference);// line 3
    }

}

// Repository - It extends from CrudRepository (insert, update, delete operations)
@Repository
public interface ServingAreaReferenceRepository extends CrudRepository<ServingAreaReferenceBean, UUID> {

    boolean existsByDescription(String description);

    boolean existsByDescriptionAndIdIsNot(String description, UUID id);
}

当“repository.save()”(第 3 行)执行时,它成功存储了用户,但我将用户逻辑放在执行保存方法之前(第 1、2 行)。所以我不认为在每个服务上重复这两行是最好的方法,相反,我想实现一个通用方法或一个通用类,在执行保存方法之前为所有 Bean 实体设置用户。

那可能吗?什么是更好的方法?

我想实现这样的东西,但不知道如何使它通用?

@Component
public class AuditableBeanHandler {

    @Inject private CloudContextProvider cloudContextProvider;

    public AuditableBean populateAuditInformation(AuditableBean auditableBean) {
        Optional<CloudContext> cloudContext = Optional.ofNullable(CloudContextProvider.get());
        auditableBean.setUpdaterUser(CloudContext.map(cloudContext::getUserId).orElse(null));
        return auditableBean;
    }

}
4

2 回答 2

0

好吧,我的理解是,您必须在实体的每次保存调用之前设置用户:

这可以通过使用称为“模板方法设计模式”的众所周知的设计模式来解决。

只需为服务类创建一个父类:

public abstract class AbstractService<T extends AuditableBean> {

        public AuditableBean populateAuditInformation(AuditableBean auditableBean) {
            Optional<CloudContext> cloudContext = Optional.ofNullable(CloudContextProvider.get());
auditableBean.setLastUpdatedByUser(CloudContext.map(cloudContext::getUserId).orElse(null));
                    return auditableBean;
                }

public absract T save(T areaReference);

public final T create(T t) {
             t = populateAuditInformation(t);
             return save(t);
            }

并在您的服务类中扩展此抽象服务并添加保存方法:

public class AreaReferenceService extends AbstractService<AreaReferenceBean> {

public AreaReferenceBean save(AreaReferenceBean AreaReference) {
        return repository.save(AreaReference);
    }
}

在调用服务方法时,调用create()方法。希望这能解决你的问题,你也可以阅读更多关于模板方法设计模式的信息。

于 2022-01-19T05:33:30.023 回答
0

我认为您与 AuditableBean 非常接近。

添加以下配置以启用审计:

// Annotate a configuration class with this
@EnableJpaAuditing(auditorAwareRef = "auditAware")

添加这个“auditAware”bean,您需要调整它以匹配您正在使用的任何身份验证机制。它的唯一目的是返回经过身份验证的用户的用户名,Spring 将使用它。

@Bean
public AuditorAware<String> auditAware() {

return () -> {
   Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
   return Optional.of(authentication.getPrincipal());
};

}

@LastModifiedBy在您的 modified_user 字段 ( ) 中再添加一个注释。AuditAware这告诉 Spring,当实体发生更新时,将此字段设置为从bean返回的值。

@Column(name = "modifier_user", nullable = false)
@LastModifiedBy
private String modifier_user;

有关可用审计字段的更多信息,请参阅Spring Data JPA 文档

于 2022-01-19T15:35:42.987 回答