原题目:Spring认证中国教育管理中心-Apache Geode 的 Spring 数据教程二十二(Spring中国教育管理中心)
Apache Geode 的 Spring 数据教程二十二
9.2.1.按区域类型的实体映射
除了@Region正文,为Apache的Geode春数据也抵赖特定类型的区域映射正文: @ClientRegion,@LocalRegion,@PartitionRegion,和@ReplicateRegion。
在性能上,这些正文的解决形式@Region与 SDG 映射基础设施中的通用正文完全相同。然而,这些额定的映射注解在 Spring Data for Apache Geode 的注解配置模型中很有用。联合@
EnableEntityDefinedRegionsSpring@Configuration注解类上的配置注解,能够在本地缓存中生成Region,无论利用是client还是peer。
这些正文让您能够更具体地理解您的应用程序实体类应该映射到什么类型的 Region,并且还会影响 Region 的数据管理策略(例如,分区 — 也称为分片 — 与复制数据)。
将这些特定于类型的区域映射正文与 SDG 正文配置模型联合应用,您不用在配置中明确定义这些区域。
9.3.存储库映射
除了应用@Region实体类上的@Region注解指定存储实体的 Region 之外,您还能够在实体的Repository接口上指定注解。无关更多详细信息,请参阅Apache Geode 存储库的 Spring 数据。
然而,假如您想Person在多个 Apache Geode 区域(例如,People 和Customers)中存储一条记录。而后你能够定义你相应的Repository接口扩大如下:
@Region("People")
public interface PersonRepository extends GemfireRepository<Person, String> {
…
}
@Region("Customers")
public interface CustomerRepository extends GemfireRepository<Person, String> {
...
}
而后,独自应用每个存储库,您能够将实体存储在多个 Apache Geode 区域中,如以下示例所示:
@Service
class CustomerService {
CustomerRepository customerRepo;
PersonRepository personRepo;
Customer update(Customer customer) {
customerRepo.save(customer);personRepo.save(customer);return customer;
}
您甚至能够将update服务办法包装在 Spring 治理的事务中,作为本地缓存事务或全局事务。
9.4.MappingPdxSerializer
Spring Data for Apache Geode 提供了一个PdxSerializer 名为的自定义实现MappingPdxSerializer,它应用 Spring Data 映射元数据来自定义实体序列化。
序列化程序还容许您应用 Spring DataEntityInstantiator形象自定义实体实例化。默认状况下,序列化程序应用
ReflectionEntityInstantiator,它应用映射实体的持久性构造函数。持久性构造函数要么是默认构造函数,要么是独自申明的构造函数,要么是显式用@PersistenceConstructor.
为了为结构函数参数提供参数,序列化器从提供的 中读取具备命名结构函数参数的字段,应用 Spring 的@Value注解 明确标识PdxReader,如上面的示例所示:
示例 4. 应用@Value实体结构函数参数
public class Person {
public Person(@Value("#root.thing") String firstName, @Value("bean") String lastName) {
…
}
}
以这种形式正文的实体类具备从 读取PdxReader并作为结构函数参数的参数值传递的“事物”字段firstname。的值lastName是一个名为“bean”的 Spring bean。
除了Apache Geode 提供的自定义实例化逻辑和策略之外EntityInstantiators,MappingPdxSerializer它还提供了远远超出 Apache Geode 本身的性能
ReflectionBasedAutoSerializer。
尽管 Apache
GeodeReflectionBasedAutoSerializer不便地应用 Java 反射来填充实体并应用正则表达式来辨认序列化器应该解决(序列化和反序列化)的类型,但与 不同MappingPdxSerializer,它不能执行以下操作:
为PdxSerializer每个实体字段或属性名称和类型注册自定义对象。
不便地辨认 ID 属性。
主动解决只读属性。
主动解决瞬态属性。
容许以null类型平安的形式进行更强壮的类型过滤(例如,不限于仅应用正则表达式表白类型)。
咱们当初MappingPdxSerializer更具体地探讨 的每个性能。
9.4.1.自定义 PdxSerializer 注册
这MappingPdxSerializer使您可能PdxSerializers依据实体的字段或属性名称和类型注册自定义。
例如,假如您曾经定义了一个建模 a 的实体类型User,如下所示:
package example.app.security.auth.model;
public class User {
private String name;
private Password password;
...
}
尽管用户名可能不须要任何非凡逻辑来序列化值,但另一方面,序列化明码可能须要额定的逻辑来解决字段或属性的敏感性质。
兴许您想在通过网络在客户端和服务器之间发送值时爱护明码,而不仅仅是 TLS,并且您只想存储加盐哈希。应用时MappingPdxSerializer,能够注册一个自定义PdxSerializer来解决用户的明码,如下:
示例 5.PdxSerializers按 POJO 字段/属性类型注册自定义
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
SaltedHashPasswordPdxSerializer应用Password 应用程序域模型类型注册利用程序定义的实例后,MappingPdxSerializer将征询自定义PdxSerializer 以序列化和反序列化所有Password对象,而不论蕴含对象(例如,User)。
然而,假如您想自定义的序列化Passwords只User对象。为此,您能够通过指定字段或属性的齐全限定名称PdxSerializer来为该User类型注册自定义Class’s,如以下示例所示:
示例 6.PdxSerializers通过 POJO 字段/属性名称注册自定义
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put("example.app.security.auth.model.User.password", new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
请留神应用齐全限定的字段或属性名称(即
example.app.security.auth.model.User.password)作为自定义PdxSerializer注册键。
你能够通过应用一个更合乎逻辑的代码片段,如上面的构造注册码: User.class.getName().concat(".password");。咱们在后面显示的示例中举荐了这一点。后面的示例试图尽可能明确地阐明注册的语义。
9.4.2.映射 ID 属性
与 Apache Geode 一样
ReflectionBasedAutoSerializer,SDGMappingPdxSerializer也可能确定实体的标识符。然而,MappingPdxSerializer这是通过应用 Spring Data 的映射元数据来实现的,特地是通过应用 Spring Data 的@Id正文查找指定为标识符的实体属性 。或者,任何名为“id”的字段或属性,未明确用 正文@Id,也被指定为实体的标识符。
例如:
class Customer {
@Id
Long id;
...
}
在这种状况下,该Customer id字段被标记为PDX类型元数据中的标识符字段,在序列化过程中调用
PdxWriter.markIdentifierField(:String) 该PdxSerializer.toData(..)办法时应用 。
9.4.3.映射只读属性
当您的实体定义只读属性时会产生什么?
首先,理解什么是“只读”属性很重要。如果您依照JavaBeans标准定义 POJO (如 Spring 所做的那样),您能够定义一个具备只读属性的 POJO,如下所示:
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
该readOnly属性是只读的,因为它不提供 setter 办法。它只有一个 getter 办法。在这种状况下,readOnly属性(不要与readOnly DomainType字段混同)被认为是只读的。
其后果是,在MappingPdxSerializer将不会尝试填充的实例时设置此属性的一个值 ApplicationDomainType的PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)反序列化过程的办法,尤其是当的值是存在于PDX序列字节。
这在您可能要返回某个实体类型的视图或投影并且只想设置可写状态的状况下很有用。兴许实体的视图或投影基于受权或其余一些规范。要害是,您能够依据应用程序的用例和要求来利用此性能。如果您心愿始终写入字段或属性,只需定义一个 setter 办法。
9.4.4.映射瞬态属性
同样,当您的实体定义transient属性时会产生什么?
transient在序列化实体时,您心愿实体的字段或属性不会被序列化为 PDX。这正是产生的事件,不像 Apache Geode 本人的
ReflectionBasedAutoSerializer,它通过 Java 反射序列化对象可拜访的所有内容。
该MappingPdxSerializer不会序列化是合格的为暂时性的任何字段或属性,无论是应用Java自身的transient关键字(在类的实例字段的状况下)或者通过应用 @Transient 对字段或属性秋季数据注解。
例如,您能够定义一个具备瞬态字段和属性的实体,如下所示:
package example;
class Process {
private transient int id;
private File workingDirectory;
private String name;
private Type type;
@Transient
public String getHostname() {
...
}
...
}
无论是Process id现场还是可读的hostname财产被写入PDX。
9.4.5.按类类型过滤
与 Apache Geode 相似
ReflectionBasedAutoSerializer,SDGMappingPdxSerializer容许您过滤序列化和反序列化的对象类型。
然而,与 Apache
GeodeReflectionBasedAutoSerializer应用简单的正则表达式来表白序列化程序处理的类型不同,SDGMappingPdxSerializer应用更弱小的 java.util.function.Predicate接口和 API 来表白类型匹配规范。
如果你喜爱应用正则表达式,你能够实现一个Predicateusing Java 的 正则表达式反对。
对于Java的丑陋的局部Predicate界面,你能够撰写Predicates通过应用便捷和适当的API办法,包含: and(:Predicate), or(:Predicate),和negate()。
以下示例显示了PredicateAPI 的运行状况:
Predicate<Class<?>> customerTypes =
type -> Customer.class.getPackage().getName().startsWith(type.getName()); // Include all types in the same package as Customer
Predicate includedTypes = customerTypes
.or(type -> User.class.isAssignble(type)); // Additionally, include User sub-types (e.g. Admin, Guest, etc)
mappingPdxSerializer.setIncludeTypeFilters(includedTypes);
mappingPdxSerializer.setExcludeTypeFilters(
type -> !Reference.class.getPackage(type.getPackage()); // Exclude Reference types
Class传递给您的 任何对象Predicate都保障不是null.
SDGMappingPdxSerializer包含对蕴含和排除类类型过滤器的反对。
排除类型过滤
默认状况下,SDG 的MappingPdxSerializer寄存器预约义Predicates该过滤器,或从以下包中排除类型:
java.*
com.gemstone.gemfire.*
org.apache.geode.*
org.springframework.*
此外,调用 和调用时的MappingPdxSerializer过滤器null对象PdxSerializer.toData(:Object, :PdxWriter)null调用PdxSerializer.fromData(:Class<?>, :PdxReader)办法时的类类型。
很容易为其余类类型或整个类型包增加排除项,只需定义 aPredicate 并将其增加到MappingPdxSerializer后面所示的。
这
MappingPdxSerializer.setExcludeTypeFilters(:Predicate<Class<?>>)办法是可加的,这意味着它将您的利用程序定义的类型过滤器与Predicates下面应用该Predicate.and(:Predicate<Class<?>>)办法批示的现有的、预约义的类型过滤器组合在一起。
然而,如果您想蕴含java.security Principal被排除类型过滤器隐式排除的类类型(例如,)怎么办?请参阅蕴含类型过滤。
蕴含类型过滤
如果要显式蕴含类类型,或笼罩隐式排除应用程序所需的类类型的类类型过滤器(例如,java.security.Principal默认状况下应用java.* 包排除类型过滤器将排除在 上MappingPdxSerializer),则只需定义适当的Predicate并将其增加到应用
MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)办法的序列化程序中,如下所示:
Predicate<Class<?>> principalTypeFilter =
type -> java.security.Principal.class.isAssignableFrom(type);
mappingPdxSerializer.setIncludeTypeFilters(principalTypeFilters);
同样,该
MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)办法,如setExcludeTypeFilters(:Predicate<Class<?>>),是可加的,因而应用 组成任何传递类型过滤器Predicate.or(:Predicate<Class<?>>)。这意味着你能够打电话setIncludeTypeFilters(:Predicate<Class<?>>) 依据须要屡次。
当蕴含类型过滤器存在时,MappingPdxSerializer当类类型未被隐式排除或当类类型被显式蕴含时,以返回 true 的形式决定是否反/序列化类类型的实例。而后,类类型的实例将被适当地序列化或反序列化。
例如,当一个类型过滤器Predicate<Class<Principal>>如后面所示被显式注册时,它会勾销对java.*包类型的隐式排除类型过滤器。