Spring data - repository abstraction
Click here to load reader
-
Upload
jakub-kohout -
Category
Software
-
view
337 -
download
9
description
Transcript of Spring data - repository abstraction
Spring DataRepository abstraction
Jakub Kohout8/2014, IBA CZ
Databázová vrstva
JDBC
ORM
DAO
Active record
Repository
Nastavení persistence
Dle JPA 2.0
persistence.xml
PersistenceUnit
spring-data-context.xml
DataSource, EntityManagerFactory, TransactionManager
database.properties
Přístupové údaje k DB
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
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, …
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
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
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);
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);
}
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)
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
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());
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
Ú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);
}
Ú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
}
Ú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" />
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
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/