Занятие №9
Spring Data
Губайдулин
Константин
О себе
Губайдулин Константин
Опыт работы:
Технологии:
Личное:
Вспомним прошлое занятие по JPA и Hibernate.
Чтобы работать с данными, мы должны:
Вы просто пишете интерфейс репозитория
И все..
dependencies {
// ...
implementation
'org.springframework.boot:spring-boot-starter-data-jpa'
// ...
}
@Entity
public class Book {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String title;
@Column
private String description;
@Column
private Integer year;
}
public interface BookRepository
extends CrudRepository<Book, Long> {
}
Domain Drive Design см. здесь
@SpringBootApplication
@EnableJpaRepositories(basePackages="pro.sisit.unit9.data")
public class SpringDataApplication {
public interface CrudRepository<T, ID>
extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
// … more functionality omitted.
}
Create Read Update Delete aka CRUD
public class BookServiceImpl implements BookService {
private final BookRepository bookRepository;
@Override
public void save(Book book) {
bookRepository.save(book);
}
@Override
public Optional<Book> findById(Long id) {
return bookRepository.findById(id);
}
}
@Test
public void testSave() {
Book book = new Book();
book.setTitle("Буратино");
book.setYear(1936);
bookRepository.save(book);
boolean founded = false;
for (Book iteratedBook : bookRepository.findAll()) {
if (iteratedBook.getTitle().equals("Буратино")
&& iteratedBook.getId() > 0) {
founded = true;
}
}
Assert.assertTrue(founded);
}
public interface BookRepository
extends CrudRepository<Book, Long> {
List<Book> findByYear(int year);
}
Определяем метод запроса, просто объявив сигнатуру этого метода
@Test
public void testFindByYear() {
Assert.assertTrue(
bookRepository.findByYear(1876)
.stream()
.anyMatch(
book ->
book.getYear() == 1876));
}
Проверяем
Ответ:
Proxy + кодогенерация
Spring "предполагает" выборку по названию метода и параметрам.
List<Book> findByTitleAndYear(String title, int year);
наименования полей сущности
Ключевые слова
Параметры метода
тип результата
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname |
|
Or | findByLastnameOrFirstname |
|
Is,Equals | findByFirstname, findByFirstnameIs, findByFirstnameEquals | … where x.firstname = ?1 |
Полный перечень см. здесь
PagingAndSortingRepository
public interface BookRepository
extends CrudRepository<Book, Long>,
PagingAndSortingRepository<Book, Long> {
}
public Page<Book> findAtPage(int pageIndex,
int pageNumber,
Direction direction,
String sortField) {
PageRequest request = PageRequest.of(
pageIndex, pageNumber, direction, sortField);
return bookRepository.findAll(request);
}
public interface BookRepository
extends CrudRepository<Book, Long>,
JpaRepository<Book, Long> {
}
public List<Book> findSame(Book book) {
return bookRepository.findAll(Example.of(book));
}
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
select
book0_.id as id1_0_,
book0_.description as descript2_0_,
book0_.title as title3_0_,
book0_.year as year4_0_
from
book book0_
where
book0_.year=1876
Specification API
public interface BookRepository
extends CrudRepository<Book, Long>,
JpaSpecificationExecutor<Book> {
}
public class BookSpecifications {
public static Specification<Book> byYearRange(int startYear, int finishYear) {
return yearLessThan(finishYear).and(yearGreaterThan(startYear));
}
public static Specification<Book> yearLessThan(int finishYear) {
return (root, query, criteriaBuilder) ->
criteriaBuilder.lessThanOrEqualTo(root.get("year"), finishYear);
}
public static Specification<Book> yearGreaterThan(int startYear) {
return (root, query, criteriaBuilder) ->
criteriaBuilder.greaterThanOrEqualTo(root.get("year"), startYear);
}
}
public List<Book> FindInRange(Book book) {
return bookRepository.findAll(
BookSpecifications.byYearRange(1800, 1900));
}
@Query - jpql
@Query("select aob.book from "
+ "AuthorOfBook aob "
+ "join aob.author "
+ "where aob.author.lastname = ?1")
List<Book> findByAuthor(String lastname);
Про jpql см. здесь
Hibernate:
select
book1_.id as id1_2_,
book1_.description as descript2_2_,
book1_.title as title3_2_,
book1_.year as year4_2_
from
author_of_book authorofbo0_
inner join
book book1_
on authorofbo0_.book_id=book1_.id
inner join
author author2_
on authorofbo0_.author_id=author2_.id
where
authorofbo0_.author_id=?
Пишем свою имплементацию
(имя репозитория + Impl)
public interface BookComplexQueryRepository {
List<Book> complexQueryMethod();
}
@Repository
public class BookComplexQueryRepositoryImpl
implements BookComplexQueryRepository {
@Override
public List<Book> complexQueryMethod() {
...
public interface BookRepository
extends CrudRepository<Book, Long>,
PagingAndSortingRepository<Book, Long>,
JpaRepository<Book, Long>,
BookComplexQueryRepository {
@Test
public void testComplexQuery() {
Assert.assertEquals(2,
bookRepository.complexQueryMethod().size());
}