In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces how to use Spring and Hibernate custom audit log, the article is very detailed, has a certain reference value, interested friends must read it!
If you need to automatically audit all database operations and you are using Hibernate... You should use Envers or spring data jpa auditing. But if for some reason you cannot use Envers, you can use hibernate event listeners and spring transaction synchronization to achieve similar functionality.
First, start with the event listener. You should capture all insert, update, and delete operations. But there is a thorny problem-if you need to refresh the session for any reason, you cannot use the session passed to the event listener to execute the logic directly. In my case, I had to get some data, and hibernate started throwing exceptions to me ("id is null"). Multiple sources confirm that you should not interact with the database in the event listener. Therefore, you should store events for later processing. You can register the listener as spring bean, as follows:
@ Componentpublic class AuditLogEventListener implements PostUpdateEventListener, PostInsertEventListener, PostDeleteEventListener {@ Override public void onPostDelete (PostDeleteEvent event) {AuditedEntity audited = event.getEntity () .getClass () .getAnnotation (AuditedEntity.class); if (audited! = null) {AuditLogServiceData.getHibernateEvents () .add (event);}} @ Override public void onPostInsert (PostInsertEvent event) {AuditedEntity audited = event.getEntity () .getClass () .getAnnotation (AuditedEntity.class) If (audited! = null) {AuditLogServiceData.getHibernateEvents () .add (event);}} @ Override public void onPostUpdate (PostUpdateEvent event) {AuditedEntity audited = event.getEntity () .getClass () .getAnnotation (AuditedEntity.class); if (audited! = null) {AuditLogServiceData.getHibernateEvents () .add (event) } @ Override public boolean requiresPostCommitHanding (EntityPersister persister) {return true;// Envers sets this to true only if the entity is versioned. So figure out for yourself if that's needed}}
Note that AuditedEntity- is a custom tag comment (retention=runtime, target=type) that you can place on top of the entity.
Since I have AuditLogServiceData for spring to use, I decided to use spring in my example:
/ * {@ link AuditLogServiceStores} stores here audit log information It records all * changes to the entities in spring transaction synchronizaton resources, which * are in turn stored as {@ link ThreadLocal} variables for each thread. Each thread * / transaction is using own copy of this data. * / public class AuditLogServiceData {private static final String HIBERNATE_EVENTS = "hibernateEvents"; @ SuppressWarnings ("unchecked") public static List getHibernateEvents () {if (! TransactionSynchronizationManager.hasResource (HIBERNATE_EVENTS)) {TransactionSynchronizationManager.bindResource (HIBERNATE_EVENTS,new ArrayList ());} return (List) TransactionSynchronizationManager.getResource (HIBERNATE_EVENTS);} public static Long getActorId () {return (Long) TransactionSynchronizationManager.getResource (AUDIT_LOG_ACTOR) } public static void setActor (Long value) {if (value! = null) {TransactionSynchronizationManager.bindResource (AUDIT_LOG_ACTOR, value);}} public void clear () {/ / unbind all resources}}
In addition to storing events, we also need to store the users who are performing operations. To get it, we need to provide a method parameter-level comment to specify a parameter. The comments in my example are called AuditLogActor (retention=runtime, type=parameter).
Now all that's left is the code to handle the event. We want to do this before committing the current transaction. If the transaction fails on commit, the audit entry insertion will also fail. Let's do this with a little bit of AOP:
@ Aspect@Componentclass AuditLogStoringAspectextends TransactionSynchronizationAdapter {@ Autowired private ApplicationContext ctx; @ Before ("execution (* *. * (.)) & @ annotation (transactional)") public void registerTransactionSyncrhonization (JoinPoint jp, Transactional transactional) {Logger.log (this) .debug ("Registering audit log tx callback"); TransactionSynchronizationManager.registerSynchronization (this); MethodSignature signature = (MethodSignature) jp.getSignature (); int paramIdx = 0 For (Parameter param: signature.getMethod (). GetParameters ()) {if (param.isAnnotationPresent (AuditLogActor.class)) {AuditLogServiceData.setActor ((Long) jp.getArgs () [paramIdx]);} paramIdx + +;}} @ Override public void beforeCommit (boolean readOnly) {Logger.log (this) .debug ("tx callback invoked. Readonly= "+ readOnly); if (readOnly) {return;} for (Object event: AuditLogServiceData.getHibernateEvents ()) {/ / handle events, possibly using instanceof}} @ Override public void afterCompletion (int status) {/ / we have to unbind all resources as spring does not do that automatically AuditLogServiceData.clear ();}
As far as I'm concerned, I had to inject extra services, and spring complained about interdependent bean, so I used applicationContext.getBean (FooBean.class) instead. Note: make sure your aspect is captured by spring-either by scanning it automatically or explicitly registering it through xml/java-config.
Therefore, the audited call will look like this:
@ Transactionalpublic void saveFoo (FooRequest request,@AuditLogActor Long actorId) {.. }
To sum up: the hibernate event listener stores all insert, update, and delete events as Spring transaction synchronization resources. One aspect registers a transaction "callback" with spring, which is called before each transaction commits. Where all events are processed and corresponding audit log entries are inserted.
This is a very basic audit log, it may have problems with collection and processing, and it certainly does not cover all use cases. But it is much better than manual audit log processing, and in many systems, audit logs are mandatory.
The above is all the contents of the article "how to use Spring and Hibernate to customize the audit log". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.