Hibernate Envers custom field for user input

我的未来我决定 提交于 2019-12-11 17:12:33

问题


I'm using Spring Boot and Hibernate Envers with a custom RevisionEntity and RevisionListener to store additional information like username, ip in the revision info. It works fine.

As a new requirement I also need to store modification comment from the user. So if a user changes an entity he/she also needs to enter a reason for this change. This text should be saved among the other revision information.

I have the text in my Controller and in the Service class as well, but how can I populate the RevisionListener with this information?


回答1:


The ideal answer to your question depends on the versions of both Hibernate and Spring Framework that you are currently using as some new features added in the later versions of both making injecting application state into the RevisionListener callback tremendously easier to obtain.

Using Hibernate 5.2 or prior

If you are using Hibernate 5.2 or prior, you're going to be restricted to the legacy approach of injecting the application state using ThreadLocal variables. In a web application, this can easily be done either by setting up a web filter or doing this as a part of your web controller.

The goal is to initialize the ThreadLocal prior to calling whatever business service/bean that performs the persistence operation and clearing the state after the persistence operation has been committed. Since most spring-based applications tend to wrap the service method in a @Transactional annotation then handling the initialization and clearing of the ThreadLocal in the controller seems logical.

Since the ThreadLocal is a global variable that is scoped to the executing thread, the listener will be able to ask the thread local instance for the value in order to set it on the custom revision entity. The most important thing is to set it before the persistence operation starts and to clear it after its saved.

Using Hibernate 5.3+ in a CDI environment

This likely doesn't apply to you since you're in a Spring environment, but for the sake of completeness of all the possible configuration choices, I'm including it.

If you are using Hibernate 5.3 or later in a CDI-based environment, Hibernate added default support for CDI injection, basically allowing certain objects created by Hibernate to actually become CDI beans and support having state injected into them. In other words

public class CustomRevisionListener implements RevisionListener {
  @Inject
  private UserReasonBean reasonBean;

  @Override
  public void newRevision(Object revisionEntity) {
    // inside this method, you can get the reason from the injected reasonBean
    // and now set the reason on the custom revision entity instance.
  }
}

Using Hibernate 5.3+ but with Spring 5.0 or prior

In order to get Spring Framework bean injection to work, you must be using Spring Framework 5.1 or later where they added that support, otherwise when using Spring Framework 5.0 or prior with Hibernate, you must use the legacy approach with ThreadLocal variables.

See Using Hibernate 5.2 or prior

Using Hibernate 5.3+ with Spring 5.1+

If you are using Hibernate 5.3 or later with Spring Framework 5.1 or later, then you're in luck. In this use case, you can mimic the default CDI support automatically because Spring Framework 5.1 provides their own bean registry implementation and wires it automatically into Hibernate's framework. In short, this means that you can easily auto-wire Spring beans into the RevisionListener just as if you were using CDI.

public class CustomRevisionListener implements RevisionListener {
  @Autowired
  private UserReasonBean reasonBean;

  @Override
  public void newRevision(Object revisionEntity) {
    // inside this method, you can get the reason from the injected reasonBean
    // and now set the reason on the custom revision entity instance.
  }
}


来源:https://stackoverflow.com/questions/56040031/hibernate-envers-custom-field-for-user-input

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!