Access EntityManager From Spring Data JPA In Spring Boot

Using Repository implementation with Spring Data, one can develop applications with an underlying database rapidly in Spring Boot. The Spring Data JPA handles the abstraction of the persistence layer quite well. Many times you probably won’t need anything else beyond what it has to offer. A lot can already be done with the exposed methods for data access from the interfaces alone.

Of course, it goes without saying that sometimes more is needed. There are limitations, and sometimes using an @Query annotation does not satisfy the requirements. This is when the need to access the EntityManager becomes handy. A more customized implementation and query can then be had once this EntityManager API can be used directly.

For example, I might need a custom solution to build a SQL query that will update a record for only those specific fields that were passed in my API endpoint. Sometimes due to business requirements, we don’t want any of the other fields to be modified, and we also don’t want to do an additional SELECT query from the database before doing said UPDATE operation manually each time.

Implementing this kind of approach of accessing the EntityManager can be done by doing the following.

Let’s start with a custom interface. Take note that the name of the interface should be named the same way as the Repository we want to extend and should end in the keyword – “Custom”. This pattern can be overridden in the Spring Data configuration, but we’re not going to take that up in this article. Below is what it would look like.

package xyz.joseyamut.repository.interfaces;

import xyz.joseyamut.dao.entity.BookEntity;

public interface BookRepositoryCustom {
    void updateBook(BookEntity entity);
}

Then we need to define the implementation for a single method in the interface, let’s make it like so – updateBook(BookEntity entity). The name of the implementing class must end in “Impl”. It extends the interface that was created above. The EntityManager is then injected and annotated with the @PersistenceContext annotation so it can interact with the persistence context. The @Transactional annotation at the method level here is more useful for writes, so that queries are done as a single atomic transaction instead of separate ones. An entity may involve more than one table here.

package xyz.joseyamut.repository.interfaces;

import xyz.joseyamut.dao.entity.BookEntity;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

@Repository
public class BookRepositoryCustomImpl implements BookRepositoryCustom {

    @PersistenceContext
    private EntityManager manager;

    @Override
    @Transactional
    public void updateBook(BookEntity entity) {

        // do some custom code logic with the EntityManager here
        
    }

Then we update the Repository interface to include the custom class like so:

package xyz.joseyamut.repository;

import xyz.joseyamut.dao.entity.BookEntity;
import xyz.joseyamut.repository.interfaces.BookRepositoryCustom;
import xyz.joseyamut.repository.interfaces.BookRepositoryCustomImpl;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EnableJpaRepositories(basePackageClasses = BookRepositoryCustomImpl.class)
public interface BookRepository extends JpaRepository<BookEntity, String>, BookRepositoryCustom {

    // something more here

}

The custom method updateBook can now be accessed directly from the defined repository class above.

// ... Other class definitions omitted

    @Autowired
    private BookRepository repository;


    public void update(BookEntity entity) {
        repository.updateBook(entity);
    }

And there we have it. Perhaps in a later blog article I’ll write about the custom update query implementation I did not so long ago.

Similar Posts:

Notice: This article was published on October 20, 2020 and the content above may be out of date.