如何解决将自定义字段添加到 Hibernate Envers 修订表 (revinfo),如 operation_id哪个是Operation实体的PK
嗨,我想知道是否可以将像 Operation_id 这样的自定义字段添加到 revinfo 表中,该表将具有自定义操作,例如 ADD_TRAVEL_OP。这些操作应该静态或动态地设置在每个端点中。
@Entity
@Table(name = "revinfo")
@RevisionEntity(AuditRevisionListener.class)
public class AuditRevisionEntity extends DefaultRevisionEntity implements Serializable {
@Column(name = "rev")
private int revision;
private String username;
private String operationId;
public int getRevision() {
return revision;
}
public void setRevision(final int revision) {
this.revision = revision;
}
public String getUsername() {
return username;
}
public void setUsername(final String userName) {
this.username = userName;
}
public String getOperationId() {
return operationId;
}
public void setOperationId(final String operationId) {
this.operationId = operationId;
}
@Configuration
public class AuditRevisionListener implements RevisionListener {
@Override
public void newRevision(Object revisionEntity) {
final AuditRevisionEntity are = (AuditRevisionEntity) revisionEntity;
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof UserDetails) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
are.setUsername(userDetails.getUsername());
} else {
are.setUsername(authentication.getName());
}
}
}
解决方法
当然,您可以向 AuditRevisionEntity 添加字段。诀窍是您必须能够访问 AuditRevisionListener 中的数据。我要求某些操作需要记录审计跟踪 (AuditRevisionEntity) 中更改的原因。我最终使用本地线程来存储更改原因,使用本地线程在 AuditRevisionListener 中设置更改原因,并在事务开始或完成时清除本地线程。
JpaTransactionManager 实现:
public class AuditingJpaTransactionManager extends JpaTransactionManager {
private final AuditContextHolder auditContextHolder = new AuditContextHolder();
public AuditingJpaTransactionManager() {
super();
}
public AuditingJpaTransactionManager(EntityManagerFactory emf) {
super(emf);
}
@Override
protected void doBegin(Object transaction,TransactionDefinition definition) {
this.auditContextHolder.clearContext();
super.doBegin(transaction,definition);
}
@Override
protected void doCleanupAfterCompletion(Object transaction) {
this.auditContextHolder.clearContext();
super.doCleanupAfterCompletion(transaction);
}
}
线程本地实现:
public class AuditContextHolder {
private static final ThreadLocal<AuditContext> contextHolder = new ThreadLocal<>();
public void clearContext() {
contextHolder.remove();
}
public AuditContext getContext() {
AuditContext ctx = contextHolder.get();
if (ctx == null) {
ctx = new AuditContext();
contextHolder.set(ctx);
}
return ctx;
}
@NoArgsConstructor
public static class AuditContext {
@Getter
@Setter
private String reasonForChange;
}
}
,
所以在 Lee Greiner 的帮助下,我实现了目标。剩下的我就放在这里,这是显而易见的,但仍然可以帮助他人。
//update to what i already had
public class AuditRevisionListener implements RevisionListener {
@Override
public void newRevision(Object revisionEntity) {
final AuditRevisionEntity are = (AuditRevisionEntity) revisionEntity;
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof UserDetails) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
are.setUsername(userDetails.getUsername());
} else {
are.setUsername(authentication.getName());
}
String operationId = new AuditContextHolder().getContext().getOperationId();
if(operationId == null) operationId = Operation.NOT_DEFINED.name();
are.setOperationId(operationId);
}
}
//Set the desired Operation before the save point
new AuditContextHolder()
.getContext()
.setOperationId(Operation.LOGIN_OP.name());
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。