将自定义字段添加到 Hibernate Envers 修订 table (revinfo),如 operation_id。哪个是Operation实体的PK
Add custom field to Hibernate Envers revision table (revinfo), like operation_id. Which is a PK of Operation entity
您好,我想知道是否可以将 Operation_id 之类的自定义字段添加到 revinfo table,它将具有自定义操作,例如 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());
您好,我想知道是否可以将 Operation_id 之类的自定义字段添加到 revinfo table,它将具有自定义操作,例如 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());