Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use declare Stream as return type when dealing with JPA Specification and spring-data-jpa

I'm wondering if I can use JPA specification predicates in custom queries?

I've tried but with no success.

Let's say I have an Entity Customer and a repository:

@Repository
public interface CustomerRepository 
    extends JpaRepository<Customer, Long>,
   JpaSpecificationExecutor<Customer> {
}

Querying like this is OK

@Query("select c from Customer c")
Stream<Customer> streamAllCustomers();

This is Not OK

Stream<Customer> streamAllCustomersWithFilter(Specification<Customer> filter);

Is there a way to achieve this ?

NB I know I can put params in the @Query but I would like to stay in the design of the current app and use Specifications all the way.

like image 237
Wajax Avatar asked Dec 21 '16 10:12

Wajax


People also ask

What is JPA stream?

Overview. JPA(Java Persistence API) specification lets you define which objects should be persisted, and how those objects should be persisted in your Java applications. JPA is considered the standard industry approach for Object to Relational Mapping (ORM) in the Java Industry.

What does findById return in JPA?

Its findById method retrieves an entity by its id. The return value is Optional<T> . Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value.

What is the return type of save method in JPA repository?

JPA's persist method returns void and Hibernate's save method returns the primary key of the entity.

Is Spring data JPA an implementation of the JPA specification?

Spring Data JPA is not an implementation or JPA provider, it's just an abstraction used to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.


Video Answer


1 Answers

There is the way to stream data from Spring Data JPA that I use. This approach is useful to process huge amount of data while avoiding high memory consumption, because whole query result is not loaded to memory.

Create custom individual repository with following implementation

public class YourCustomRepositoryImpl implements YourCustomRepository {

    @PersistenceContext(unitName = "yorEntityManagerFactory")
    private EntityManager em;

    @Override
    public Stream<SomeEntity> streamAll(Specification<SomeEntity> spec) {

            CriteriaBuilder cb = em.getCriteriaBuilder();
            CriteriaQuery<SomeEntity> query = cb.createQuery(SomeEntity.class);
            Root<SomeEntity> root = query.from(SomeEntity.class);
            query.where(spec.toPredicate(root, query, cb));

            return em.createQuery(query).getResultStream();
    }

}

Sure, this requires JPA 2.2 supporting ORM framework (I used Hibernate 5.3).

Also, you should care to provide a connection to be alive while stream is being processed.

like image 90
Eugene Avatar answered Nov 06 '22 12:11

Eugene