Wednesday, September 18, 2019

Introduction to Spring Data JPA

In the last project, I have used two main modules of Spring Data family i.e. Spring Data JPA which provides Spring Data repository support for JPA & Spring Data REST for exporting Spring Data repositories as hypermedia-driven RESTful resources. Today, we would be discussing Spring Data JPA, it's benefits, and why one should use it?

1. Introduction


With JPA, we are already implementing the data access layer of our application but the real question was, do we think our efforts and time are justified in writing too much boilerplate code to execute simple queries as well as perform pagination, and auditing. Spring Data JPA aims to significantly improve the implementation of data access layers.

2. What is Spring Data JPA


Let us first understand what Spring Data JPA is not?
  • Unlike the JPA, which is a specification that defines the API for ORM and for managing persistent objects, Spring Data JPA is not a specification. 
  • Spring Data JPA is not a JPA provider like Hibernate. 
Spring Data JPA is a library/framework that adds an extra layer of abstraction on the top of JPA that makes a developer's life easy by providing a way to easily implement JPA based repositories. As a developer, one has to write the repository interfaces, including custom finder methods, and Spring would automatically provide the implementation.

3.  Why Spring Data JPA


Anyone who has worked in implementing data access layer (DAO) of a traditional enterprise application using JPA & Hibernate would surely understand how much code must be written in order to interact with the database for CRUD operations. Not only that, one might have to write a similar CRUD operation code for other entities. It simply signifies that implementing a data access layer of an application is cumbersome and also leads to a lot of boilerplate code. We would see the glimpse of  DAO(Data Access Object) implementation using both the approaches i.e. JPA+ Hibernate VS Spring Data JPA + Hibernate. One could decide for themselves, which one is better? 

JPA + Hibernate DAO Implementation


package anshulsblog.spring.web.daoImpl;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;


@Repository
public class SampleDaoImpl implements SampleDao {

    @PersistenceContext(unitName = "jpa_unit")
    private EntityManager entityManager;
    private final Logger logger = Logger.getLogger(SampleDaoImpl.class);

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
 
    @Override
    @Transactional
    public boolean editUserName(Long userId, String userName) {
        logger.info("SampleDaoImpl : editUserName");
        boolean isEdited = true;
        try {
            StringBuilder sb = new StringBuilder(" UPDATE user u ");
            sb.append(" SET u.userName = ? ");
            sb.append(" WHERE  u.userid = ? ");
            String sql = sb.toString();
            Query nativeQuery = getEntityManager().createNativeQuery(sql);
            nativeQuery.setParameter(1, userName);
            nativeQuery.setParameter(2, userId);
            nativeQuery.executeUpdate();
            getEntityManager().flush();
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            isEdited = false;
        }
        return isEdited;
    }

    @Override
    public String getUserName(Long userId) {
        logger.info("SampleDaoImpl : getUserName");
        String userName = "";
        try {
            StringBuilder sb = new StringBuilder(" SELECT u.username FROM user u ");
            sb.append(" WHERE u.id = ? ");
            String sql = sb.toString();
            Query nativeQuery = getEntityManager().createNativeQuery(sql);
            nativeQuery.setParameter(1, userId);
            List resultList = nativeQuery.getResultList();

            if (!resultList.isEmpty()) {
                for (int i = 0; i < resultList.size(); i++) {
                    userName = resultList.get(i).toString();
                }
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }
        return userName;
    }
}

Spring Data JPA + Hibernate

Here we have created the Repository Interface and Spring would automatically provide the implementation. To know more about various Spring Data Repository interfaces, their functionality and how to build a repository, check out this article.

package com.anshulsblog.repository;
 
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;

import com.anshulsblog.model.User;
 
public interface UserRepository extends CrudRepository<User, Long> {

@Transactional( readOnly = true )
User findByUserId(Long uesrId);

@Modifying
@Transactional
@Query(value ="UPDATE User u set u.userName = :username where u.userid = :userId")
boolean editUserName(@Param("userid") Long userId, @Param("username") String userName)
}

Have you noticed anything in the above implementation?

You got it right. The first method doesn't have any query attached to it. But it would give us the desired results. Thinking how? Here, Spring Data JPA is generating database queries based on the method names.

Just saying, in the second method also, we have used JPQL that means even if we change our underlying database it would work without any change.

4. Spring Data JPA Features


  • Sophisticated support to build repositories based on Spring and JPA 
  • Validation of @Query annotated queries at the bootstrap time - For testing purpose, try writing some wrong query then one would notice detailed logs explaining the errors in query and application would not start. 
  • Pagination support, dynamic query execution, ability to integrate custom data access code
  • Transparent auditing of the domain class

5. Conclusion 


Hoping that we all have understood the main reason or motivation behind the arrival of Spring Data JPA. The pain that it takes away, the repetitive tasks that developers don't have to do again and again while implementing the data access layers. Happy Learning!!

No comments:

Post a Comment