Skip to content

Spring Data

Spring Data helps you access and manipulate data in databases without writing tons of code.

Key Features:

  • Repository Abstraction: You define an interface, and Spring Data auto-generates the implementation.
  • Query Methods: Write queries by just naming your methods (like findByUsername()).
  • Support for Many Data Stores:
    • Relational (JPA/Hibernate, JDBC)
    • NoSQL (MongoDB, Neo4j, Redis, Cassandra, etc.)
    • Pagination and Sorting
    • Custom Queries using JPQL, native SQL, or annotations

Repository

Data Access Object level. Interface remains constant independent of the DB behind it.

Repository (Marker-Interface) -> CRUDRepository -> PagingAndSortingRepository

Derived Queries

Queries generated by Spring Data based on the signature.

Methods only need to be defined in the interface. No implementation is required.

Examples

  • findByFirstNameAndLastName(String name, String lastname) -> And queries
  • findByFirstNameOrderByCreated(String name) -> Ordering
  • deleteByName(String name) -> Deletion
  • findByAgeGreaterThan -> Less than, greater than, etc
  • CountBy -> Results as long
  • readBy
  • getBy
  • queryBy
  • findFirst -> returns first entry

AND-OR

Any And, Or Keywords

java
findByFirstNameAndLastName

EQUALS-IS-NOT

java
List<Session> findBySessionLengthNot(Integer length);

LIKE- NOT LIKE

Placeholder: %

java
List<Session> findBySessionNameNotLike(String name);

STARTING/ENDING WITH – CONTAINING

java
List<Session> findBySessionNameStartingWith(String name);

LESS THAN – GREATER THAN

java
List<Session> findBySessionLengthLessThan(Integer length);

BEFORE – AFTER – BETWEEN

For Date/Time-Queries

TRUE – FALSE

For boolean fields

java
List<TicketType> findByIncludesWorkshopTrue();

NULL – NOT NULL

Null, isNull, notNull, isNotNull

java
List <Speaker> findBySpeakerPhotoNull();

IN – NOT IN

java
...in(Collection<Daten>)
java
List <Speaker> findByCompanyIn(List<String> companies);

IGNORE CASE

java
List<Speaker> findCompanyIgnoreCase(String company);

ORDER BY

java
List<Speaker> findByLastNameOrderByFirstNameAsc(String lastName);

FIRST – TOP – DISTINCT

java
findTop5ByFirstName

Paging and Sorting

java
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);

Or add paging and sorting as parameters to the derived queries.

java
final Page<Flight> page=flightRepository.findByOrigin("London",PageRequest.of(0,5,Sort.by(Sort.Order.desc("destination"))));

or

java
@Query("select * from Session s where s.sessionName like %:name")
Page<Session> getSessionWithName(@Param("name") String name, Pageable page);

Custom Module

Extend the repository with custom implementation

  • Create a new interface
  • Implement the interface
  • Existing interface now also extends the CustomRepository interface
java
public interface DeleteByOriginRepository {
    void deleteByOrigin(String origin);
}

public class DeleteByOriginRepositoryImpl implements DeleteByOriginRepository{
    private final EntityManager entityManager;

    public DeleteByOriginRepositoryImpl(EntityManager entityManager){
        this.entityManager=entityManager;
    }

    @Override
    public void deleteByOrigin(String origin) {
        entityManager.createNativeQuery("DELETE from flight where origin =?").setParameter(1, origin).executeUpdate();
    }
}

Extend existing repository with new functionality

java
public interface FlightRepository extends PagingAndSortingRepository<Flight, Long>, DeleteByOriginRepository{
    List<Flight> findByOrigin(String london);

    List<Flight> findByOriginAndDestination(String london, String paris);

    List<Flight> findByOriginIn(String ... origins);

    List<Flight> findByOriginIgnoreCase(String origin);

    Page<Flight> findByOrigin(String origin, Pageable pageRequest);
}

Transactions

@Transactional – Annotation to work within a transaction. Reduces boilerplate code, more stable, DB independent…

Tests

Annotate with @SpringBootTest

Spring Data JPA

• Extends JPA • Simplifies the data layer • JpaRepositories • Query DSL • Data tier (sorting, paging, etc.) • Optional. Can easily be bypassed if necessary

Configuration

Pom.xml

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

<!-- Dependency for Postgres JDBC driver -->
<dependency>
   <groupId>org.postgresql</groupId>
   <artifactId>postgresql</artifactId>
   <scope>runtime</scope>
</dependency>
properties
Application.properties
spring.datasource.url=jdbc:postgresql:conference_app
spring.datasource.username=
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.show-sql=true

Repository

java
public interface SpeakerJpaRepository extends JpaRepository<Speaker,Long> {
}

Query-Annotation

For custom queries. Add method with @Query annotation to repository.

java
@Query("Select tp from TicketPrice tp where tp.basePrice < ?1 "+
        "and tp.ticketType.includesWorkshop = true"
        )
List<TicketPrice> getTicketsUnderPriceWithWorkshops(BigDecimal maxPrice);

?1 First parameter is replaced with parameter of the method.

Named Parameter

Instead of numbered parameters, parameter names can be used.

java
@Query("Select tp from TicketPrice tp where tp.basePrice < :maxprice "+
        "and tp.ticketType.includesWorkshop = true"
        )
List<TicketPrice> getTicketsUnderPriceWithWorkshops(@Param(“maxprice”) BigDecimal maxPrice);

Enhanced JPQL Syntax

“… where s.sessionName like %?1” Platzhalter ‘%’ kann hinzugefügt werden

Native SQL Query

java
@Query(value=“select \* from sessions s where s.session_name= ?0”, nativeQuery = true)
List<Session> getSessionsWithName(String name);

Modifiable Queries

java
@Modifying
@Query("update Session s set s.sessionName = ?1")
int updateSessionName(String name);

NamedQueries

Named Queries are predefined JPQL (Java Persistence Query Language) queries and are validated at the start of the app They are located on the entity, repository or as named attribute by the query annotation

java
@Entity
@NamedQuery(
    name = "User.findByEmail",
    query = "SELECT u FROM User u WHERE u.email = :email"
)
public class User

NamedNativeQuery

java
@Entity
@NamedNativeQuery(
    name = "User.findByEmail",
    query = "SELECT * FROM users WHERE email = ?",
    resultClass = User.class
)
public class User

Query priority

  1. @Query-Annotation
  2. Named/NativeNamed-Queries
  3. Query-DSL Naming

Auditing

Annotation of entity properties

  • @CreatedBy
  • @LastModifiedBy
  • @CreatedDate (automatically defined)
  • @LastModifiedDate (automatically defined)

Locking

java
@Version-Annotation in Entity
@Version
private int version

@Lock(LockModeType.PESSIMISIC_WRITE)
List<Model> findByAttributeName(String name)

Contact: M_Bergmann AT gmx.at