Data JPA and Querydsl (Spring Boot)

Introduction

For Spring Data JPA Projections, see page 'Data JPA':

https://sites.google.com/site/pawneecity/sprint-boot/data-jpa-spring-boot

Reference

See 'Query Methods' (section 6.3)

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference


https://www.baeldung.com/rest-api-search-language-spring-data-querydsl


http://www.querydsl.com/static/querydsl/latest/reference/html_single/


@Transactional

At business methods (@Transactional)

The annotation can only be used in instance (non-static) methods of Beans (Services, Components, etc.).

Warning: Since Spring proxies the class, the method must be invoked from another class to take effect!


At repo methods (@Transactional)

Reference > https://www.wilfriedbarth.com/til/2018-03-31-spring-transactional-annotation/

Error:

No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call; nested exception is javax.persistence.TransactionRequiredException


Apparently, Spring only marks the default methods of the CrudRepository interface as transactional, so any custom methods that you define yourself won't be managed by the EntityManager. The fix for this is quite simple. Just mark the custom method with @Transactional and the EntityManager will recognize it as a transaction.

import org.springframework.transaction.annotation.Transactional;


  /**

   * Delete by academic record

   */

  @Modifying

  @Transactional

  void deleteByNotifAcademicRecordId_AcademicRecordCode(Long academicRecordCode); // NOSONAR


Note: 

findById(id) retrieves an entity -- Avoids the no Session exception in unit tests

getOne(id) returns a reference to the entity -- no Session exception in unit tests

Querydsl

There is an incompatibility with Java 11 and plugin com.mysema.maven:apt-maven-plugin:1.1.3 that deletes generated files.

Workaround: Use plugin version 1.1.2 instead.

Examples

Delete

  /**

   * Delete by id.academic record

   */

  @Transactional

  void deleteByNotifAcademicRecordId_AcademicRecordCode(Long academicRecordCode); // NOSONAR

Pagination

 We can choose to return either a Page<T>, a Slice<T> or a List<T> from any of our custom methods returning a paginated data. A Page<T> also knows the total number of available pages, using an additional count query.

It also, optionally, supports sorting.

Repo method:

Slice<Milestone> findByMilestoneGatStatusNot(final String milestoneGatStatusCode, Pageable pageable);

Usage:

    Slice<Milestone> slice;

    int pageIndex = 0;

    

    do {

      Pageable pageable = PageRequest.of(pageIndex, 1024);

      slice = this.milestoneRepo.findByMilestoneGatStatusNot(

          milestoneAchievedStatusCode, pageable);

      

      List<Milestone> records = slice.getContent();

  

      /* whatever */

      

      //Increase page index

      pageIndex++;

    } while (slice.hasNext());

-