本指南将引导您使用 Apache Geode 数据管理系统来构建应用程序。
你要构建的内容
你将使用 Spring Data for Apache Geode 来存储和检索 POJOs。
所需内容
-
大约 15 分钟
-
一个常用的文本编辑器或 IDE
-
Java 1.8 或以上版本
-
你也可以直接将代码导入到你的 IDE 中:
如何完成本指南
和大多数 Spring 入门指南一样,你可以从零开始并完成每一步,也可以跳过已熟悉的基本设置步骤。不管选择哪种方式,你最终都能获得可运行的代码。
要从头开始,请参阅使用 Spring Initializr 开始。
若要跳过基础知识,请执行以下操作:
-
下载并解压此指南的源代码仓库,或者使用Git进行克隆:
git clone https://github.com/spring-guides/gs-accessing-data-gemfire.git
-
进入
gs-accessing-data-gemfire/initial
目录 -
跳到定义一个简单的实体。
完成之后,你可以将你的结果与 gs-accessing-data-gemfire/complete
中的代码进行对比。
从 Spring Initializr 开始
你可以使用这个预初始化的项目,并点击 Generate 下载 ZIP 文件。该项目已配置为适用于本教程中的示例。
手动初始化项目:
-
在网页浏览器中访问 https://start.spring.io。该服务会为你拉取所有必要的依赖项,并自动完成大部分配置工作。
-
请选择所需的构建工具(Gradle 或 Maven)和编程语言。本指南假设您选择了 Java。
-
点击依赖项,然后选择Spring for Apache Geode。
-
点击生成。
-
下载生成的ZIP文件,这是根据您的选择配置的一个Web应用程序的归档文件。
如果你的IDE集成了Spring Initializr,你可以在IDE中直接完成这个过程。 |
你也可以从 Github 获取该项目,并在你的 IDE 或其他编辑器中打开它。 |
定义简单实体
Apache Geode 是一个内存数据网格(IMDG),它将数据映射到区域。你可以配置分布式区域,以便在集群中的多个节点之间分区和复制数据。然而,在本指南中,我们使用 LOCAL
区域,这样你无需设置额外的服务器集群等。
Apache Geode 是一个键值存储,而区域实现了 java.util.concurrent.ConcurrentMap
接口。虽然你可以将区域视为 java.util.Map
,但由于数据在区域内是分布式的、复制的,并且通常由区域进行管理,因此它比简单的 Java Map
要复杂得多。
在这个例子中,你将使用几个注解,把 Person
对象存储到 Apache Geode 的一个区域中。
src/main/java/hello/Person.java
package hello;
import java.io.Serializable;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.gemfire.mapping.annotation.Region;
import lombok.Getter;
@Region(value = "People")
public class Person implements Serializable {
@Id
@Getter
private final String name;
@Getter
private final int age;
@PersistenceConstructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return String.format("%s is %d years old", getName(), getAge());
}
}
这里有一个包含两个字段(name
和 age
)的 Person
类。你还有一个用于在创建新实例时填充实体的单个持久化构造函数。该类使用Project Lombok 来简化实现。
请注意,此类使用了@Region("People")
注解。当Apache Geode存储此类的一个实例时,会在People
区域中创建一个新的条目。该类还用@Id
标记了name
字段,这表示用于在Apache Geode内部标识和跟踪Person
数据的唯一标识符。本质上,带有@Id
注解的字段(如name
)是键,而Person
实例则是该键/值条目的值。在Apache Geode中没有自动的键生成功能,因此必须在将实体持久化到Apache Geode之前设置ID(即name
字段)。
下一个重要的是人的年龄。在本指南的后续部分,我们将使用它来构建一些查询。
重写后的 toString()
方法会输出该人的姓名和年龄。
创建简单查询
Spring Data for Apache Geode 专注于使用 Spring 在 Apache Geode 中存储和访问数据,并继承了 Spring Data Commons 项目的一些强大功能,例如推导查询的能力。因此,你无需学习 Apache Geode 的查询语言(OQL)。只需编写几个方法,框架就会自动生成相应的查询。
为了了解其工作原理,创建一个用于查询存储在 Apache Geode 中的 Person
对象的接口。
src/main/java/hello/PersonRepository.java
package hello;
import org.springframework.data.gemfire.repository.query.annotation.Trace;
import org.springframework.data.repository.CrudRepository;
public interface PersonRepository extends CrudRepository<Person, String> {
@Trace
Person findByName(String name);
@Trace
Iterable<Person> findByAgeGreaterThan(int age);
@Trace
Iterable<Person> findByAgeLessThan(int age);
@Trace
Iterable<Person> findByAgeGreaterThanAndAgeLessThan(int greaterThanAge, int lessThanAge);
}
PersonRepository
继承了 Spring Data Commons 中的 CrudRepository
接口,并为泛型类型参数指定了值和 ID(键)的具体类型,分别为 Person
和 String
。此接口提供了许多操作,包括基本的 CRUD 操作(创建、读取、更新、删除),以及简单的查询数据访问操作,例如 findById(..)
。
你可以通过声明方法签名来定义其他查询。在这种情况下,我们添加了findByName
,它会搜索类型为Person
的对象,并找到一个在name
属性上匹配的对象。
你还有:
-
findByAgeGreaterThan
: 查找某一年龄以上的人 -
findByAgeLessThan
: 查找低于特定年龄的人 -
findByAgeGreaterThanAndAgeLessThan
: 用于查找特定年龄范围内的人
让我们来配置一下,看看效果如何!
创建应用程序类
以下示例创建了一个包含所有组件的应用程序类:
src/main/java/hello/Application.java
package hello;
import static java.util.Arrays.asList;
import static java.util.stream.StreamSupport.stream;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
@SpringBootApplication
@ClientCacheApplication(name = "AccessingDataGemFireApplication")
@EnableEntityDefinedRegions(
basePackageClasses = Person.class,
clientRegionShortcut = ClientRegionShortcut.LOCAL
)
@EnableGemfireRepositories
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
ApplicationRunner run(PersonRepository personRepository) {
return args -> {
Person alice = new Person("Adult Alice", 40);
Person bob = new Person("Baby Bob", 1);
Person carol = new Person("Teen Carol", 13);
System.out.println("Before accessing data in Apache Geode...");
asList(alice, bob, carol).forEach(person -> System.out.println("\t" + person));
System.out.println("Saving Alice, Bob and Carol to Pivotal GemFire...");
personRepository.save(alice);
personRepository.save(bob);
personRepository.save(carol);
System.out.println("Lookup each person by name...");
asList(alice.getName(), bob.getName(), carol.getName())
.forEach(name -> System.out.println("\t" + personRepository.findByName(name)));
System.out.println("Query adults (over 18):");
stream(personRepository.findByAgeGreaterThan(18).spliterator(), false)
.forEach(person -> System.out.println("\t" + person));
System.out.println("Query babies (less than 5):");
stream(personRepository.findByAgeLessThan(5).spliterator(), false)
.forEach(person -> System.out.println("\t" + person));
System.out.println("Query teens (between 12 and 20):");
stream(personRepository.findByAgeGreaterThanAndAgeLessThan(12, 20).spliterator(), false)
.forEach(person -> System.out.println("\t" + person));
};
}
}
在配置中,需要添加@EnableGemfireRepositories
注解。
-
默认情况下,
@EnableGemfireRepositories
会扫描当前包中继承了 Spring Data 存储库接口的所有接口。你可以使用其basePackageClasses = MyRepository.class
参数来安全地指定 Spring Data for Apache Geode 按类型扫描不同的根包,以查找特定于应用程序的 Repository 扩展。
需要一个包含一个或多个区域的 Apache Geode 缓存来存储所有数据。为此,你可以使用 Spring Data for Apache Geode 提供的配置注解之一:@ClientCacheApplication
、@PeerCacheApplication
或 @CacheServerApplication
。
Apache Geode 支持不同的缓存拓扑结构,例如客户端/服务器、对等(P2P)以及广域网(WAN)配置。在 P2P 模式下,对等缓存实例嵌入到应用程序中,并且您的应用程序可以作为集群中的对等缓存成员参与其中。然而,由于您的应用程序受制于集群中对等成员的所有约束条件,因此这种模式不像客户端/服务器拓扑那样常用。
在这种情况下,我们使用 @ClientCacheApplication
来创建一个“客户端”缓存实例,该实例能够连接并与其他服务器集群进行通信。然而,为了简化起见,客户端通过使用 LOCAL
客户端区域在本地存储数据,而无需设置或运行任何服务器。
现在回想一下,你是如何使用 SDG 映射注解 @Region("People")
将 Person
标记为存储在名为 People
的区域中的?在这里,你通过定义 ClientRegionFactoryBean<String, Person>
的 bean 来创建该区域。你需要注入刚刚定义的缓存实例,并将其命名为 People
。
A Apache Geode 缓存实例(无论是对等实例还是客户端)只是一个存储区域的容器,这些区域保存你的数据。你可以将缓存视为关系型数据库管理系统中的模式,将区域视为表。然而,缓存还执行其他管理功能来控制和管理所有区域。 |
类型为<String, Person> ,其中键的类型是String ,值的类型是Person 。 |
public static void main
方法使用 Spring Boot 的 SpringApplication.run()
来启动应用程序,并通过应用的 Spring Data 仓库调用 ApplicationRunner
(另一个 bean 定义),在 Apache Geode 上执行数据访问操作。
PersonRepository
实例。Spring Data for Apache Geode 动态创建了一个实现此接口的具体类,并插入所需的查询代码以满足接口的要求。在 run()
方法中使用这个 repository 实例来演示其功能。
存储和检索数据
Person
对象: Alice、Baby Bob 和 Teen Carol。最初,这些对象只存在于内存中。创建之后,你需要将它们保存到 Apache Geode 中。
现在你可以运行多个查询。第一个查询是根据姓名查找所有人。接着,你可以通过年龄属性来运行几个查询,分别找出成年人、婴儿和青少年。如果开启了日志记录功能,你还可以查看 Spring Data for Apache Geode 自动为你生成的查询。
要查看 SDG 生成的 Apache Geode OQL 查询,可以将 @ClientCacheApplication 注解中的 logLevel 属性设置为 config 。由于查询方法(如 findByName )使用了 SDG 的 @Trace 注解,这会开启 Apache Geode 的 OQL 查询跟踪(即查询级别的日志记录),从而显示生成的 OQL、执行时间、是否使用了任何 Apache Geode 索引来收集结果以及返回的行数。 |
构建可执行的 JAR 包
你可以通过 Gradle 或 Maven 从命令行运行应用程序。你也可以构建一个包含所有必需依赖项、类和资源的单个可执行 JAR 文件并运行它。这样可以轻松地在整个开发生命周期中,在不同的环境中打包、版本控制和部署服务。
如果你使用 Gradle,可以通过运行 ./gradlew bootRun
来启动应用程序。或者,你也可以通过运行 ./gradlew build
构建 JAR 文件,并按如下方式运行该 JAR 文件:
java -jar build/libs/gs-accessing-data-gemfire-0.1.0.jar
如果你使用 Maven,可以通过运行 ./mvnw spring-boot:run
来启动应用。或者,你可以通过执行 ./mvnw clean package
构建 JAR 文件,然后按照以下方式运行该 JAR 文件:
java -jar target/gs-accessing-data-gemfire-0.1.0.jar
这里描述的步骤创建了一个可执行的 JAR 文件。你也可以构建一个经典的 WAR 文件。 |
你应该看到类似的内容(可能包括其他项,例如查询):
Before linking up with {apache-geode-name}... Alice is 40 years old. Baby Bob is 1 years old. Teen Carol is 13 years old. Lookup each person by name... Alice is 40 years old. Baby Bob is 1 years old. Teen Carol is 13 years old. Adults (over 18): Alice is 40 years old. Babies (less than 5): Baby Bob is 1 years old. Teens (between 12 and 20): Teen Carol is 13 years old.
摘要
恭喜您!您已成功设置了 Apache Geode 缓存客户端,存储了简单实体,并开发了快速查询。
参见
以下指南可能也会有所帮助: