Spring data - repository abstraction

18

Click here to load reader

description

Basic info and usage abour Spring data repository abstraction

Transcript of Spring data - repository abstraction

Page 1: Spring data - repository abstraction

Spring DataRepository abstraction

Jakub Kohout8/2014, IBA CZ

Page 2: Spring data - repository abstraction

Databázová vrstva

JDBC

ORM

DAO

Active record

Repository

Page 3: Spring data - repository abstraction

Nastavení persistence

Dle JPA 2.0

persistence.xml

PersistenceUnit

spring-data-context.xml

DataSource, EntityManagerFactory, TransactionManager

database.properties

Přístupové údaje k DB

Page 4: Spring data - repository abstraction

Architektura JPA 2.0

Persistence Unit

• Množina všech typů entit, které mohou být spravovány Entity Managerem a které se vážou k jedné DB.

• Application-managed EM / Container –managed EM / JTA EM

Persistence Context

• Množina instancí spravovaných entit

• EM řídí jejich životní cyklus

EntityManagerFactory

• Poskytuje instance EM

• Všechny EM mají stejnou konfiguraci

• Obdoba Session Factory

Entity Manager

• Určen k přístupu do databáze a práci s perzistentními entitami

• Obdoba Session

Page 5: Spring data - repository abstraction

Spring Data

Snaha zjednodušit implementaci databázové vrstvy

Využívá Repository abstrakcí

Rozhraní Repository

Marker interface - typovatelné na doménové objekty a jejich id

Rozšiřující rozhraní:

poskytují sadu metod pro práci s entitami

CrudRepository - nahrazuje použití JpaDaoSupport a JpaTemplate

PagingAndSortingRepository – rozšiřuje CrudRepository

JpaRepository – rozšiřuje PagingAndSortingRepository

Implementace:

JPA, Apache Hadoop, Mongo DB, GemFire, …

Page 6: Spring data - repository abstraction

CrudRepository

public interface CrudRepository<T, ID extendsSerializable> extends Repository<T, ID> {

T save(T entity);

T findOne(ID primaryKey);

Iterable<T> findAll();

Long count();

void delete(T entity);

boolean exists(ID primaryKey);

// … more functionality omitted.

}

• Všechny CRUD metody jsou @Transactional by default

Page 7: Spring data - repository abstraction

Vytvoření Repository rozhraní

Musí rozšiřovat alespoň Repository<T, ID extends Serializable>

rozhraní

public interface UserRepository extends JpaRepository<User, Long>{

User getByUsername(String username);

List<User> findByRoleAndPrivilage(Role role, Privilage privilage);

. . .

}

SimpleJpaRepository - Defaultní implementace JpaRepository

Page 8: Spring data - repository abstraction

Dotazování

Pomocí názvu metody

Název metody je složen z klíčových slov (and, or, between…)

public interface UserRepository extends Repository<User, Long> {

List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);

}

Vytvoří dotaz:

select u from User u where u.emailAddress = ?1 and u.lastname = ?2

Další možnosti

Long countByLastname(String lastname);

Long deleteByLastname(String lastname);

List<User> removeByLastname(String lastname);

List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);

Page 9: Spring data - repository abstraction

Dotazování

Pomocí @NamedQuery

Musí být definována pomocí JPQL

Alternativa @NamedNativeQuery

Také pomocí XML deklarace

@Entity

@NamedQuery(name = "User.findByEmail", query = "select u from User u where u.emailAddress = ?1")

public class User { }

public interface UserRepository extends JpaRepository<User, Long> {

User findByEmail(String emailAddress);

}

Page 10: Spring data - repository abstraction

Klíčová slova metodKeyword Sample JPQL snippet

And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2

Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2

Is,EqualsfindByFirstname,findByFirstnameIs,findByFirst

nameEquals… where x.firstname = 1?

Between findByStartDateBetween … where x.startDate between 1? and ?2

LessThan findByAgeLessThan … where x.age < ?1

LessThanEqual findByAgeLessThanEqual … where x.age <= ?1

GreaterThan findByAgeGreaterThan … where x.age > ?1

GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1

After findByStartDateAfter … where x.startDate > ?1

Before findByStartDateBefore … where x.startDate < ?1

IsNull findByAgeIsNull … where x.age is null

IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null

Like findByFirstnameLike … where x.firstname like ?1

NotLike findByFirstnameNotLike … where x.firstname not like ?1

StartingWith findByFirstnameStartingWith… where x.firstname like ?1 (parameter bound

with appended %)

EndingWith findByFirstnameEndingWith… where x.firstname like ?1 (parameter bound

with prepended %)

Containing findByFirstnameContaining… where x.firstname like ?1 (parameter bound

wrapped in %)

OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc

Not findByLastnameNot … where x.lastname <> ?1

In findByAgeIn(Collection<Age> ages) … where x.age in ?1

NotIn findByAgeNotIn(Collection<Age> age) … where x.age not in ?1

True findByActiveTrue() … where x.active = true

False findByActiveFalse() … where x.active = false

IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

Page 11: Spring data - repository abstraction

Dotazování

Pomocí @Query

JPQL@Query("select u from User u where u.firstname like %?1")

List<User> findByFirstnameEndsWith(String firstname);

nativní SQL po nastavení flagu nativeQuery=true

@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?0", nativeQuery = true)

User findByEmailAddress(String emailAddress);

pojmenované parametry, modifikovatelné dotazy, transakce@Query("update Trip t set t.tripStatus = :tripStatus where t.tripId = :tripId")

@Modifying*

@Transactional

public int setNewTripStatus(@Param("tripStatus") TripStatusType tripStatus, @Param("tripId") Long tripId);

*@Modifying umožňuje nastavit clearAutomatically – vyčistí persistenční kontext po updatu

Page 12: Spring data - repository abstraction

Využití Criteria – Querydsl

support

Rozšíření rozhraní JpaSpecificationExecutorpublic interface CustomerRepository extends CrudRepository<Customer, Long>,

JpaSpecificationExecutor{}

Zpřístupňuje metody jako:

List<T> findAll(Specification<T> spec);

Definice Specification rozhraní:public static Specification<Customer> isLongTermCustomer() {

return new Specification<Customer>() {

public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,

CriteriaBuilder builder) {

LocalDate date = new LocalDate().minusYears(2);

return builder.lessThan(root.get(Customer_.createdAt), date);

}

};}

Použití:List<Customer> customers = customerRepository.findAll(isLongTermCustomer());

Page 13: Spring data - repository abstraction

Konfigurace

1. Maven dependency

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-jpa</artifactId>

<version>1.6.2.RELEASE</version>

</dependency>

2. Nastavení component scan pro automatické vyhledání Repositoryinstancí:

<jpa:repositories base-package="com.ts.repository" />

Nutné přidat nový namespace - xmlns:jpa=http://www.springframework.org/schema/data/jpa

instance Repository jsou registrovány pod jménem rozhraní

element repositories – možné explicitně definovat EntityManagerFartory, PlatformTransactionManager

parametr named-query-locations – umožňuje načítat předdefinované query z propertiessouboru

Page 14: Spring data - repository abstraction

Úpravy rozhraní – odebrání

nepotřebných metod

Pokud nechceme používat všechny poskytované

metody:

interface MyBaseRepository<T, ID extends Serializable> extendsRepository<T, ID> {

T findOne(ID id);

T save(T entity);

}

Page 15: Spring data - repository abstraction

Úpravy rozhraní – obohacení

konkrétního rozhraní

Vytvoření doplňujícího rozhraní s vlastními metodami

1. interface UserRepositoryCustom {

public void someCustomMethod(User user);

}

2. class UserRepositoryImpl implements UserRepositoryCustom {

public void someCustomMethod(User user) {

// Your custom implementation

} }

3. public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {

// Declare query methods here

}

Page 16: Spring data - repository abstraction

Úpravy rozhraní – vytvoření

vlastního společného Repository

rozhraní Rozšíření existujícího rozhraní1. public interface MyJpaRepository<T, ID extends Serializable> extends

JpaRepository<T, ID> {

public void sharedCustomMethod(ID id);

...

}

2. public class MyRepositoryImpl<T, ID extends Serializable> extendsSimpleJpaRepository<T, ID> implements MyRepository<T, ID> {

public void sharedCustomMethod(ID id) {

// implementation goes here

}

}

3. public class MyRepositoryFactoryBean<T extends JpaRepository<?, ?> extendsJpaRepositoryFactoryBean<T> {

. . .

}

3. <jpa:repositories base-package="com..repository„

factory-class="com..MyRepositoryFactoryBean" />

Page 17: Spring data - repository abstraction

Další funkce Volani databázových procedur

@NamedStoredProcedureQuery – nad deklarací entity

@Procedure(procedureName = "plus1inout") – nad signaturou z rozhraní

Uzamykání záznamů

@Lock(LockModeType.READ);

Použití SpEl

public interface UserRepository extends JpaRepository<User,Long> {

@Query("select u from #{#entityName} u where u.lastname = ?1")

List<User> findByLastname(String lastname);

}

Stránkování

@Query("select m from Message m where m.portletId = :portletId order by m.codeasc, m.language asc")

public Page<Message> findByPortletId(@Param("portletId") String portletId,

Pageable pageable);

Fetch-/LoadGraph

@EntityGraph(value = "GroupInfo.detail", type = EntityGraphType.LOAD)

Auditing

Page 18: Spring data - repository abstraction

Shrnutí

Ulehčuje psaní data access vrstvy

Snadno použitelné

Snadno rozšiřitelné

Využívá znalostí z JPA

http://docs.spring.io/spring-data/