乐趣区

关于spring:Spring认证中国教育管理中心Spring-Data-Neo4j教程四

原题目:Spring 认证中国教育管理中心 -Spring Data Neo4j 教程四(Spring 中国教育管理中心)

Spring 认证:Spring Data Neo4j 教程四
6.3.3. 个别倡议
尝试保持应用不可变对象 ——不可变对象很容易创立,因为实现对象只需调用其构造函数即可。此外,这能够避免您的域对象被容许客户端代码操纵对象状态的 setter 办法乱扔垃圾。如果您须要这些,最好将它们包爱护起来,以便它们只能被无限数量的并置类型调用。仅构造函数实现比属性填充快 30%。
提供一个全参数的构造函数 ——即便你不能或不想将你的实体建模为不可变值,提供一个将实体的所有属性作为参数(包含可变属性)的构造函数依然有价值,因为这容许对象映射以跳过属性填充以获得最佳性能。
应用工厂办法而不是重载的构造函数来防止 @PersistenceConstructor - 应用最佳性能所需的全参数构造函数,咱们通常心愿公开更多特定于应用程序用例的构造函数,这些构造函数省略主动生成的标识符等内容。这是一种既定的模式,而不是应用动态工厂办法来公开这些全参数构造函数的变体。
确保恪守容许应用生成的实例化器和属性拜访器类的束缚
对于要生成的标识符,依然应用 final 字段联合 wither 办法
应用 Lombok 防止样板代码 - 因为持久性操作通常须要一个构造函数来获取所有参数,因而它们的申明变成了对字段调配的样板参数的繁琐反复,应用 Lombok 能够最好地防止这种状况 @AllArgsConstructor。
对于不可变映射的阐明
只管咱们倡议尽可能应用不可变映射和结构,但在映射方面存在一些限度。给定一个双向关系,其中 A 有一个构造函数援用 B 和 B 一个援用 A,或者更简单的场景。Spring Data Neo4j 无奈解决这种先有后有的状况。在它的实例化过程中,A 它迫切需要一个齐全实例化的,B 另一方面,它须要一个. SDN 通常容许这样的模型,但会抛出一个 AMappingException 如果从数据库返回的数据蕴含上述星座,则在运行时。在这种状况下,您无奈预感返回的数据是什么样的,您更适宜应用可变字段来解决关系。

6.3.4.Kotlin 反对
Spring Data 调整了 Kotlin 的细节以容许对象创立和变异。

Kotlin 对象创立
Kotlin 类反对实例化,默认状况下所有类都是不可变的,须要明确的属性申明来定义可变属性。思考以下 data 类 Person:

data class Person(val id: String, val name: String)
下面的类编译为具备显式构造函数的典型类。咱们能够通过增加另一个构造函数来自定义这个类,并用正文 @PersistenceConstructor 来批示构造函数的偏好:

data class Person(var id: String, val name: String) {

@PersistenceConstructor
constructor(id: String) : this(id, "unknown")

}
Kotlin 通过在未提供参数时容许应用默认值来反对参数可选性。当 Spring Data 检测到具备参数默认值的构造函数时,如果数据存储不提供值(或简略地返回 null),它将使这些参数不存在,因而 Kotlin 能够利用参数默认值。思考以下利用参数默认值的类 name

data class Person(var id: String, val name: String = “unknown”)
每次 name 参数不是后果的一部分或其值为 null 时,name 默认为 unknown。

Kotlin 数据类的属性总体
在 Kotlin 中,默认状况下所有类都是不可变的,并且须要显式的属性申明来定义可变属性。思考以下 data 类 Person:

data class Person(val id: String, val name: String)
这个类实际上是不可变的。它容许创立新实例,因为 Kotlin 生成一个 copy(…)创立新对象实例的办法,该办法从现有对象复制所有属性值并将作为参数提供的属性值利用到该办法。

  1. 应用 Spring 数据存储库
    Spring Data repository 形象的指标是显着缩小为各种持久性存储实现数据拜访层所需的样板代码量。

Spring Data 存储库文档和您的模块

本章介绍 Spring Data 存储库的外围概念和接口。本章中的信息来自 Spring Data Commons 模块。它应用 Java Persistence API (JPA) 模块的配置和代码示例。您应该调整 XML 名称空间申明和要扩大的类型,以适应您应用的特定模块的等效项。“[
repositories.namespace-reference]”涵盖了 XML 配置,所有反对存储库 API 的 Spring Data 模块都反对该配置。“附录 A”涵盖了存储库形象个别反对的查询方法关键字。

7.1 外围概念
Spring Data 存储库形象中的地方接口是 Repository. 它须要域类来治理以及域类的 ID 类型作为类型参数。此接口次要用作标记接口,以捕捉要应用的类型并帮忙您发现扩大此接口的接口。该 CrudRepository 接口为被治理的实体类提供了简单的 CRUD 性能。

示例 13.CrudRepository 接口

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.
}
保留给定的实体。

返回由给定 ID 标识的实体。

返回所有实体。

返回实体的数量。

删除给定的实体。

批示具备给定 ID 的实体是否存在。

咱们还提供了特定于持久性技术的形象,例如 JpaRepository 或 MongoRepository。CrudRepository 除了相当通用的与持久性技术无关的接口(例如 CrudRepository.

Spring 认证:Spring Data Neo4j 教程四
在 之上 CrudRepository,还有一个
PagingAndSortingRepository 形象,它增加了额定的办法来简化对实体的分页拜访:

示例
14.PagingAndSortingRepository 界面

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

Iterable<T> findAll(Sort sort);

Page<T> findAll(Pageable pageable);
}
要拜访 User 页面大小为 20 的第二页,您能够执行以下操作:

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));
除了查询方法之外,还能够应用计数和删除查问的查问派生。以下列表显示了派生计数查问的接口定义:

示例 15. 派生计数查问

interface UserRepository extends CrudRepository<User, Long> {

long countByLastname(String lastname);
}
以下清单显示了派生删除查问的接口定义:

示例 16. 派生删除查问

interface UserRepository extends CrudRepository<User, Long> {

long deleteByLastname(String lastname);

List<User> removeByLastname(String lastname);
}
7.2. 查询方法
规范 CRUD 性能存储库通常对底层数据存储进行查问。应用 Spring Data,申明这些查问变成了一个四步过程:

1. 申明一个扩大 Repository 或其子接口之一的接口,并将其键入应解决的域类和 ID 类型,如以下示例所示:

interface PersonRepository extends Repository<Person, Long> {…}
2. 在接口上申明查询方法。

interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLastname(String lastname);
}
3. 设置 Spring 以应用 JavaConfig 或 XML configuration 为这些接口创立代理实例。

a. 要应用 Java 配置,请创立一个相似于以下内容的类:

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EnableJpaRepositories
class Config {…}
b. 要应用 XML 配置,请定义一个相似于以下内容的 bean:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:jpa=”http://www.springframework.org/schema/data/jpa”
xsi:schemaLocation=”http://www.springframework.org/schema/beans

 https://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/data/jpa
 https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

<jpa:repositories base-package=”com.acme.repositories”/>

</beans>
此示例中应用了 JPA 命名空间。如果您将存储库形象用于任何其余存储,则须要将其更改为存储模块的适当命名空间申明。换句话说,您应该替换 jpa,例如,mongodb。另外请留神,JavaConfig 变体没有显式配置包,因为默认应用带正文的类的包。要自定义要扫描的包,请应用特定于数据存储的存储库的 -annotation 的 basePackage…属性之一。@Enable${store}Repositories

4. 注入存储库实例并应用它,如下例所示:

class SomeClient {

private final PersonRepository repository;

SomeClient(PersonRepository repository) {

this.repository = repository;

}

void doSomething() {

List<Person> persons = repository.findByLastname("Matthews");

}
}
.3. 定义存储库接口
要定义存储库接口,您首先须要定义特定于域类的存储库接口。接口必须扩大 Repository 并输出到域类和 ID 类型。如果要公开该域类型的 CRUD 办法,请扩大 CrudRepository 而不是 Repository.

7.3.1. 微调存储库定义
通常,您的存储库接口会扩大 Repository、CrudRepository 或
PagingAndSortingRepository. 或者,如果您不想扩大 Spring Data 接口,也能够应用 @RepositoryDefinition. 扩大 CrudRepository 公开了一整套操作实体的办法。如果您心愿对公开的办法有选择性,请将要公开的办法复制 CrudRepository 到您的域存储库中。

这样做能够让您在提供的 Spring Data Repositories 性能之上定义本人的形象。

以下示例显示了如何选择性地公开 CRUD 办法(在本例中为 findById 和 save):

示例 17. 选择性地公开 CRUD 办法

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {

Optional<T> findById(ID id);

<S extends T> S save(S entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
User findByEmailAddress(EmailAddress emailAddress);
}
在后面的示例中,您为所有域存储库定义了一个通用的根本接口,并公开 findById(…)了 save(…)这些办法。这些办法被路由到 Spring Data 提供的您抉择的存储的根本存储库实现(例如,如果您应用 JPA,实现是 SimpleJpaRepository),因为它们与 CrudRepository. 所以 UserRepository 当初能够保留用户,通过 ID 查找单个用户,并触发查问以 Users 通过电子邮件地址查找。

两头存储库接口用 @NoRepositoryBean. 确保将该正文增加到 Spring Data 不应在运行时为其创立实例的所有存储库接口。

7.3.2. 将存储库与多个 Spring 数据模块一起应用
在应用程序中应用惟一的 Spring Data 模块会使事件变得简略,因为定义范畴内的所有存储库接口都绑定到 Spring Data 模块。有时,应用程序须要应用多个 Spring Data 模块。在这种状况下,存储库定义必须辨别持久性技术。当检测到类门路上有多个存储库工厂时,Spring Data 进入严格的存储库配置模式。严格配置应用存储库或域类的详细信息来决定存储库定义的 Spring Data 模块绑定:

如果存储库定义扩大了特定于模块的存储库,则它是特定 Spring Data 模块的无效候选者。
如果域类应用特定于模块的类型正文进行正文,则它是特定 Spring Data 模块的无效候选者。Spring Data 模块承受第三方注解(例如 JPA’s @Entity)或提供本人的注解(例如 @DocumentSpring Data MongoDB 和 Spring Data Elasticsearch)。
以下示例显示了应用特定于模块的接口(在本例中为 JPA)的存储库:

示例 18. 应用模块特定接口的存储库定义

interface MyRepository extends JpaRepository<User, Long> {}

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> {…}

interface UserRepository extends MyBaseRepository<User, Long> {…}
MyRepository 并在它们的类型层次结构中 UserRepository 扩大。JpaRepository 它们是 Spring Data JPA 模块的无效候选者。

以下示例显示了应用通用接口的存储库:

示例 19. 应用通用接口的存储库定义

interface AmbiguousRepository extends Repository<User, Long> {…}

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> {…}

interface AmbiguousUserRepository extends MyBaseRepository<User, Long> {…}
AmbiguousRepository 并仅在其类型层次结构中 AmbiguousUserRepository 扩大。尽管在应用惟一的 Spring Data 模块时这很好,但多个模块无奈辨别这些存储库应该绑定到哪个特定的 Spring Data。RepositoryCrudRepository

以下示例显示了一个应用带正文的域类的存储库:

示例 20. 应用带正文的域类的存储库定义

interface PersonRepository extends Repository<Person, Long> {…}

@Entity
class Person {…}

interface UserRepository extends Repository<User, Long> {…}

@Document
class User {…}

PersonRepositoryreferences Person,应用 JPA@Entity 正文进行正文,因而这个存储库显然属于 Spring Data JPA。UserRepositoryreferences User,应用 Spring Data MongoDB 的注解进行 @Document 注解。

以下谬误示例显示了一个应用具备混合正文的域类的存储库:

示例 21. 应用具备混合正文的域类的存储库定义

interface JpaPersonRepository extends Repository<Person, Long> {…}

interface MongoDBPersonRepository extends Repository<Person, Long> {…}

@Entity
@Document
class Person {…}
此示例显示了应用 JPA 和 Spring Data MongoDB 正文的域类。它定义了两个存储库,JpaPersonRepository 并且 MongoDBPersonRepository. 一个用于 JPA,另一个用于 MongoDB。Spring Data 不再可能辨别存储库,这会导致未定义的行为。

存储库类型详细信息和辨别域类正文用于严格的存储库配置,以辨认特定 Spring Data 模块的存储库候选者。在同一域类型上应用多个持久性技术特定的正文是可能的,并且能够跨多个持久性技术重用域类型。然而,Spring Data 无奈再确定绑定存储库的惟一模块。

辨别存储库的最初一种办法是确定存储库根底包的范畴。根本包定义了扫描存储库接口定义的终点,这意味着将存储库定义放在适当的包中。默认状况下,注解驱动配置应用配置类的包。基于 XML 的配置中的根本包是必须的。

以下示例显示了根本包的正文驱动配置:

示例 22. 根本包的正文驱动配置

@EnableJpaRepositories(basePackages = “com.acme.repositories.jpa”)
@EnableMongoRepositories(basePackages = “com.acme.repositories.mongo”)
class Configuration {…}

退出移动版