Spring Data JPA

Spring

Провел некоторое исследование Spring Data JPA, в основном ссылаясь на официальную Spring Data JPA - справочную документацию.

IntroductionDependenciesWorking with Spring Data RepositoriesRepositoriesQuery methodsQuery creationNamingStrategyUsing @QueryUsing SortUsing PageableSave methodsDelete methodsWhy use Spring Date JPA

Introduction

официальное определение
Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.

Чтобы объяснить, что такое Spring Data JPA, нам нужно начать шаг за шагом:
Сначала JAVA требовалось обращаться к базе данных через API, предоставляемый различными производителями баз данных.JDBC, программа может напрямую использовать спецификацию JDBC для подключения к каждой базе данных;
Затем родилсяORMПоявляются технологии, упрощающие сохранение объектов Java, и фреймворки ORM, такие как Hibernate и TopLink;
Когда Sun была в JDK1.5, она вобрала в себя преимущества Hibernate, TopLink и других сред ORM и предложилаСпецификация сохраняемости Java: JPA;

Hibernate обеспечивает реализацию JPA в версии 3.2 и других поставщиков JPA, таких как OpenJPA, Toplink и т. д.;
Spring выполняет работу по сохранению и разработал серию пакетов Spring-data-xxx, таких как: Spring-data-jpa, Spring-data-redis, Spring-data-mongodb и т. д. Все они предоставляются Spring. Репозиторий на основе JPA и некоторых других NOSQL.

http://stackoverflow.com/questions/16148188/spring-data-jpa-versus-jpa-whats-the-difference
Long story short, then, Spring Data JPA provides a definition to implement repositories that is supported under the hood by referencing the JPA specification, using the provider you define.

Spring Data JPA обеспечивает реализацию уровня репозитория на основе спецификации JPA, но вам нужно решить, какую ORM использовать; по сравнению с более привычными Hibernate и MyBatis, Spring Data JPA можно рассматривать как абстракцию более высокого уровня.

Dependencies

Для конкретных шагов, пожалуйста, обратитесь к официальному сайту:[spring-data-jpa/quick-start](https://spring.io/projects/spring-data-jpa)

<dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
    </dependency>
</dependencies>

Если вы хотите использовать Spring Data JPA под Spring Boot, вам необходимо ввести:

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

Working with Spring Data Repositories

Давайте рассмотрим простой пример реализации функции добавления, удаления, проверки и изменения; из примера мы можем обнаружить, что эффекта SQL можно добиться, определив имя метода:

Например, findByName(имя строки) эквивалентно выбору * от пользователя, где имя = ?

public interface UserCrudRepository extends CrudRepository<User, String>{

    User findOne(String userid);

    List<User> findByName(String name);

    List<User> findByNameAndAgeLessThan(String name, int age);

    void deleteByNameAndAgeLessThan(String name, int age);

    List<User> findDistinctByName(String name);

    List<User> findByNameIgnoreCase(String name);

    User findFirstByOrderByUseridDesc();
}

Repositories

Spring Date JPA предоставляет несколько интерфейсов:

  • Репозиторий:Интерфейс верхнего уровня — это пустой интерфейс, цель которого — унифицировать типы всех репозиториев и разрешить автоматическое распознавание компонентов при сканировании.
  • CrudRepository:Это субконфиксированный репозиторий и обеспечивает функции CRUD.
  • Репозиторий подкачки и сортировки:Это подинтерфейс CrudRepository, добавляющий функции подкачки и сортировки.
  • JpaРепозиторий:Это подчиненный интерфейс PagingAndSortingRepository, который добавляет такие функции, как пакетные операции.

Вышеупомянутые четыре XxxRepositoty становятся все более и более конкретными и богатыми функциями.С точки зрения использования, они должны наследовать минимальный набор, который они используют.Если их необходимо расширить и настроить, можно напрямую наследовать JpaRepository, если он хлопотный.

Query methods

Query creation

Методы findOne и findAll в CrudRepository можно использовать напрямую:

public interface UserCrudRepository extends CrudRepository<User, String>{
    /**
     * CrudRepository 中存在的方法,这里可以不写此方法 
     */
    User findOne(String userid);


    /**
     * 查询所有 可以不写此方法(继承父类)
     * 这里不写此方法,需要在查询完成后强转:
     * List<User> userAfterDel = (List<User>) this.repository.findAll();
     * 
     * 这里写此方法:
     * List<User> userAfterDel = this.repository.findAll();
     */
    List<User> findAll();
}

Метод запроса также может быть расширен, расширенный формат: найти… По, прочитать… По, запрос… По, получить… По, подсчитать… По:

public interface UserCrudRepository extends CrudRepository<User, String>{
    /**
     * 按照姓名查询,非主键:
     * @param name
     * @return
     */
    List<User> findByName(String name);

    List<User> queryByName(String name);

    /**
     * 按照姓名查询,并且年龄小于入参:
     * @param name
     * @return
     */
    List<User> findByNameAndAgeLessThan(String name, int age);

    List<User> findDistinctByName(String name);

    List<User> findByNameIgnoreCase(String name);
}

Если поле базы данных с символами [_], категория JAVA Entity с соответствующим атрибутом не [_], требует ("имя =") путем связывания тега @Column.

Если свойства в классе Entity JAVA названы в соответствии с форматом верблюжьего регистра, они также должны быть связаны с тегом @Column(name = "").

NamingStrategy

Чтобы решить вторую проблему выше: если свойства в классе Entity JAVA названы в соответствии с форматом верблюжьего регистра, их также необходимо связать с помощью тега @Column(name = "").

Интерфейс NamingStrategy в JPA (впервые предложенный в Hibernate) реализует функции именования имени таблицы и имени столбца в интерфейсе и может выполнять собственную настройку стратегии именования.

Например, мы часто сталкиваемся с такой проблемой, таблица указана с: User_id, user_name ..., если свойства в user.java не, тогда вам нужно использовать тег @Column для привязки к полям базы данных:

@Entity
@Table(name = "USER")
@Data
public class User {
  @Column(name = "user_id")
  @Id
  private String userId;

  @Column(name = "user_name")  //如果这样的字段很多,也是一个比较大的工作量
  private String userName;
}

И благодаря реализации интерфейса NamingStrategy функция горба для подчеркивания может быть выполнена единообразно, userId → user_id, userName → user_name;

Spring Boot предоставляет свойства Configure JPA, которые мы можем настроить непосредственно в application.yml:

spring.jpa.hibernate.naming.physical-strategy = com.example.MyPhysicalNamingStrategy

В Hibernate5 предусмотрены две стратегии отображения:

  • spring.jpa.hibernate.naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    Без каких-либо изменений userId → userId, userid → userid
  • spring.jpa.hibernate.naming.physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
    Измените горб на подчеркивание, userId → user_id, если не настроено, политика по умолчанию
@Entity
@Table(name = "USER")
@Data
public class User {
  @Id
  private String userId;  //不需要在使用@Column(name = "user_id"),会自动转成 user_id

  private String userName; //自动转成 user_name
}

В то же время возникнет проблема, если правила имена столбцов таблицы базы данных не являются едиными, например, некоторые подчеркнутые и некоторые не подчеркивают, затем при приготовлении объекта, подчеркнутого поля приглашенного формата, поля не подчеркиваются Написано в полном фоне, это выглядит довольно странно.

@Entity
@Table(name = "USER")
@Data
public class User {
  @Id
  private String userId;  //不需要在使用@Column(name = "user_id")

  private String userName;

  private String cardid;  //列名为 cardid ,不带下划线,所以这里不能写成驼峰格式,但是从代码风格上看,感觉比较怪异
}

Если есть более специальные требования, например, все таблицы или поля в базе имеют префикс фиксированного формата, таблица CSC_USER, поля имеют CSC_USER_ID, CSC_USER_NAME, можно реализовать интерфейс NamingStrategy самостоятельно (если это Spring Boot, то нужно быть реализованным
PhysicalNamingStrategy), добавьте в него имя префикса.

Using @Query

Используйте аннотацию @Query для привязки операторов SQL (кажется, не более интуитивно писать так):

public interface UserCrudRepository extends CrudRepository<User, String>{
    //@Query("select u from User u where u.name = ?1")
    //@Query("select u from User u where 1=1 and u.name = ?1")
    //@Query("select u.userid from User u where 1=1 and u.name = ?1")
    //@Query(value="select * from User u where u.name = ?1", nativeQuery = true)
    List<User> findByName(String name);
}

Используйте аннотацию @Param, чтобы связать имя в параметре с именем в запросе:

public interface UserCrudRepository extends CrudRepository<User, String>{
    @Query("select u from User u where u.name = :name and u.gender = :gender")
    List<User> findUsersByNameAndGender(@Param("name")String name , @Param("gender")String gender);
}

Using Sort

public interface UserCrudRepository extends CrudRepository<User, String>{
    List<User> findByOrderByUseridDesc(); //按 Userid 倒序
}

Вы также можете наследовать PagingAndSortingRepository и использовать Sort для сортировки:

public interface UserPageRepository extends PagingAndSortingRepository<User, String> {  
    List<User> findAll(Sort sort);
}

Using Pageable

Требуется расширение PagingAndSortingRepository или выше JpaRepository.

public class UserPageRepositoryTest {
  @Test
  public void findPageable() throws Exception {
    Page<User> usersPageOne = this.repository.findAll(new PageRequest(0, 2)); 

    //1.PageRequest(int page, int size) 
    //2.page从0开始
    assertThat(usersPageOne.getContent().size()).isEqualTo(2);
    assertThat(usersPageOne.getContent().get(0).getUserId()).isEqualTo("1");

    assertThat(usersPageOne.hasPrevious()).isEqualTo(false);  //判断是否有上一页

    Page<User> usersPageTwo = this.repository.findAll(usersPageOne.nextPageable());  //查询下一页
    assertThat(usersPageTwo.getContent().size()).isEqualTo(2);
    assertThat(usersPageTwo.getContent().get(0).getUserId()).isEqualTo("3");
  }
}

Вы также можете использовать ключевые слова [first] или [top], чтобы получить первые N фрагментов данных в результирующем наборе.

public interface UserCrudRepository extends CrudRepository<User, String>{
    User findFirstByOrderByUseridDesc();

    User findFirstByGenderOrderByUseridDesc(String gender);
}

Save methods

Для сохранения объекта требуется использование метода CrudRepository.save(…), включая Insert и Update.

Delete methods

Метод Delete может в основном ссылаться на метод Query.В дополнение к delete() и deleteAll() вы также можете использовать метод deleteBy…, а также тег @query.

В интерфейсе JpaRepository предусмотрен метод deleteInBatch():
Deletes the given entities in a batch which means it will create a single {@link Query}.

Why use Spring Date JPA

Видно, что по сравнению с широко используемыми Hibernate и MyBatis, Spring Data JPA более лаконичен в кодировании и сокращает Boilerplate Code.

На самом деле запросы транзакционных микросервисных приложений обычно простоПодробный запрос или простой запрос списка, а реальный сложный запрос или анализ данных обычно должен заключаться в создании другого приложения или полнотекстового поиска или ODS/DW и т. д., а также синхронизации данных из транзакционных микросервисов, и эта часть заключается в использовании MyBatis или NOSQL.

Хотя Feign не решает проблемы в той же области, что и Spring Data Repository, философия реализации последовательна, а Boilerplate Code, вызываемый Rest, минимизируется за счет интерфейсов и COC.

@FeignClient(url = "https://api.github.com")
interface GitHubClient {   
    @RequestMapping(method = RequestMethod.GET, value = "/repos/{owner}/{repo}/contributors")
    List<Contributor> contributors(@RequestParam("owner") String owner, @RequestParam("repo") String repo);
}

Дядя, который знает код | Текст [Оригинал]


会点代码的大叔
Дядя, который знает код