DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Advanced Search and Filtering API Using Spring Data and MongoDB
  • Manage Hierarchical Data in MongoDB With Spring
  • Spring Data: Data Auditing Using JaVers and MongoDB
  • CRUD Operations on Deeply Nested Comments: Scalable Spring Boot and Spring Data approach

Trending

  • Medallion Architecture: Why You Need It and How To Implement It With ClickHouse
  • Ethical AI in Agile
  • AI's Dilemma: When to Retrain and When to Unlearn?
  • A Deep Dive Into Firmware Over the Air for IoT Devices
  1. DZone
  2. Data Engineering
  3. Databases
  4. Spring Data JPA Auditing: Automatically Saving the Good Stuff

Spring Data JPA Auditing: Automatically Saving the Good Stuff

Auditing provides valuable information, but it can be a nightmare to implement. Fortunately, through Spring Data JPA, you can persist the columns you need.

By 
Naresh Joshi user avatar
Naresh Joshi
DZone Core CORE ·
May. 24, 17 · Tutorial
Likes (28)
Comment
Save
Tweet
Share
149.8K Views

Join the DZone community and get the full member experience.

Join For Free

In any business application, auditing simply means tracking and logging every change we do in our persisted records, which simply means tracking every insert, update, and delete operation and storing it.

Auditing helps us in maintaining history records, which can later help us in tracking user activities. If implemented properly, auditing can also provide us similar functionality to version control systems.

I have seen projects storing these things manually. Doing so becomes very complex because you will need to write it completely on your own, which will definitely require lots of code — and lots of code means less maintainability and less focus on writing business logic.

But why should someone need to go to this path when both JPA and Hibernate provide automatic auditing, which we can be easily configured in your project? 

Here in this article, I will discuss how we can configure JPA to automatically persist the CreatedBy, CreatedDate, LastModifiedBy, and LastModifiedDate columns for any entity.

Spring-Data-JPA-Automatic-Auditing-Saving-CreatedBy-CreatedDate-LastModifiedBy-LastModifiedDate-Automatically

I will walk you through to the necessary steps and code that you will need to include in your project to automatically update these properties. We will use Spring Boot, Spring Data JPA, and MySQL to demonstrate this. We will need to add the following parent and dependencies to our POM file:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>


Spring Data Annotations @CreatedBy, @CreatedDate, @LastModifiedBy, and @LastModifiedDate

Let’s suppose we have a File entity, and a single record in the file table stores the name and content of the file. And say we also want to store who created and modified any file at any given time. So, the goal is to keep track of when the file was created, by whom, and when it was last modified, and by whom.

We will need to add the name, content, createdBy, createdDate, lastModifiedBy, and lastModifiedDate properties to our File entity and, to make it more appropriate, we can move the createdBy, createdDate, lastModifiedBy, lastModifiedDate properties to a base class, Auditable, and annotate this base class with @MappedSuperClass. Later, we can use the Auditable class in other audited entities.

You will also need to write getters, setters, constructors, toString, and equals along with these fields. However, you should take a look at   Project Lombok: The Boilerplate Code Extractor, if you want to auto-generate these things.

Both classes will look like this:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<U> {

    @CreatedBy
    protected U createdBy;

    @CreatedDate
    @Temporal(TIMESTAMP)
    protected Date creationDate;

    @LastModifiedBy
    protected U lastModifiedBy;

    @LastModifiedDate
    @Temporal(TIMESTAMP)
    protected Date lastModifiedDate;



}

@Entity
public class File extends Auditable<String> {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String content;


}


As you can see above, I have used the @CreatedBy, @CreatedDate, @LastModifiedBy, and @LastModifiedDate annotation on their respective fields.

The Spring Data JPA approach abstracts working with JPA callbacks and provides us these fancy annotations to automatically save and update auditing entities.

Using the AuditingEntityListener Class With @EntityListeners

Spring Data JPA provides a JPA entity listener class, AuditingEntityListener, which contains the callback methods (annotated with the @PrePersist and @PreUpdate annotations), which will be used to persist and update these properties when we will persist or update our entity.

JPA provides the @EntityListeners annotation to specify callback listener classes, which we use to register our AuditingEntityListener class.

However, we can also define our own callback listener classes if we want to and specify them using the @EntityListeners annotation. In my next article, I will demonstrate how we can use @EntityListeners to store audit logs.

Auditing Author Using AuditorAware and Spring Security

JPA can analyze createdDate and lastModifiedDate using current system time, but what about the createdBy and lastModifiedBy fields? How will JPA recognize what to store in them?

To tell JPA about currently logged-in users, we will need to provide an implementation of AuditorAware and override the getCurrentAuditor() method. And inside getCurrentAuditor(), we will need to fetch a currently logged-in user.

As of now, I have provided a hard-coded user, but if you are using Spring Security, then use it to find the currently logged-in user. 

public class AuditorAwareImpl implements AuditorAware<String> {

    @Override
    public String getCurrentAuditor() {
        return "Naresh";


    }
}


Enable JPA Auditing by Using @EnableJpaAuditing

We will need to create a bean of type AuditorAware and will also need to enable JPA auditing by specifying @EnableJpaAuditing on one of our configuration classes. @EnableJpaAuditing accepts one argument, auditorAwareRef, where we need to pass the name of the AuditorAware bean.

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
    @Bean
    public AuditorAware<String> auditorAware() {
        return new AuditorAwareImpl();
    }
}


And now, if we will try to persist or update a file object, the CreatedBy, CreatedDate, LastModifiedBy, LastModifiedDate properties will automatically get saved.

In the next article, JPA Auditing: Persisting Audit Logs Automatically using EntityListeners, I will discuss how we can use JPA EntityListeners to create audit logs and generate history records for every insert, update, and delete operation.

You can find complete code on this GitHub repository, and please feel free to give your valuable feedback.

Spring Data Spring Framework Database Data (computing)

Published at DZone with permission of Naresh Joshi, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Advanced Search and Filtering API Using Spring Data and MongoDB
  • Manage Hierarchical Data in MongoDB With Spring
  • Spring Data: Data Auditing Using JaVers and MongoDB
  • CRUD Operations on Deeply Nested Comments: Scalable Spring Boot and Spring Data approach

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!