51
© 2012 SpringSource, A division of VMware. All rights reserved Spring Data in a Nutshell Tsuyoshi Miyake (@tsuyokb)

Spring Data in a Nutshell

Embed Size (px)

Citation preview

Page 1: Spring Data in a Nutshell

© 2012 SpringSource, A division of VMware. All rights reserved

Spring Data in a Nutshell

Tsuyoshi Miyake (@tsuyokb)

Page 2: Spring Data in a Nutshell

22

背景と動機

§ RDBMS はいまだ重要かつ支配的• ただ “one size fits all” ではなくなってきている

§ Spring はデータアクセスに常に優れたサポートを行ってきた§ Spring Data project のゴールは Spring のデータサポートを “リフレッシュ” すること

• Traditional: JDBC, JPA• New: Grid, Document, Graph, K-V (aka NoSQL or NewSQL)

§ なじみの一貫性のある Springベースのプログラミングモデルを提供• 個々の技術的特徴はいかしながら

§ データアクセス層から boiler-plate code をなくす• 異なるテクノロジーをまたがって利用できる共通のインタフェース

Page 3: Spring Data in a Nutshell

33

Spring Data は “umbrella project”

§ http://www.springframework.org/spring-data§ JPA - Repositories§ JDBC Extensions§ MongoDB – Document Database§ Neo4j – Graphs Database§ Redis – Key Value Database§ Gemfire – Distributed Data Grid§ Commons – shared abstractions

• Repositories• Object Mapping

§ QueryDSL – integration with type-safe query API

Page 4: Spring Data in a Nutshell

44

Spring Data Repositories (1/3)

public interface CrudRepository<T, ID extends Serializable> extendsRepository<T, ID> {

T save(T entity);

Iterable<T> save(Iterable<? extends T> entities);

T findOne(ID id);

boolean exists(ID id);

Iterable<T> findAll();

long count();

void delete(ID id);

void delete(T entity);

void delete(Iterable<? extends T> entities);

void deleteAll();}

public interface Repository<T, ID extends Serializable> {// マーカーインタフェース ex.) Repository<Customer, Long>

}

Page 5: Spring Data in a Nutshell

55

Spring Data Repositories (2/3)

public interface PagingAndSortingRepository<T, ID extends Serializable> extendsCrudRepository<T, ID> {

Iterable<T> findAll(Sort sort);

Page<T> findAll(Pageable pageable);}

§ “naming conventions” によるクエリメソッドの定義

public interface PersonRepository extends CrudRepository<Person,BigInteger> {

// Finder for a single entityPerson findByEmailAddress(String emailAddress);

// Finder for a multiple entitiesList<Person> findByLastnameLike(String lastName);

// Finder with paginationPage<Person> findByFirstnameLike(String firstName, Pageable page);

}

Page 6: Spring Data in a Nutshell

66

Spring Data Repositories (3/3)

@NoRepositoryBeanpublic interface BaseRepository<T, ID extends Serializable> extends

Repository<T, ID> {Iterable<T> findAll(Pageable sort);

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

<S extends T> S save(Iterable<S> entities);}

§ Custom Repository インタフェースの定義• CRUD は便利だが Read のみを提供したい、または Delete は提供したくない etc.

§ 定義方法1. Repository を継承(or @RepositoryDefinition を付与)したインタフェースを定義2. 公開したいメソッドのみをそのインタフェースに定義(ただし、メソッドシグネチャーは Spring Data Repository と同一にする)

3. 出来上がったインタフェースを entity のベースに

Page 7: Spring Data in a Nutshell

77

Spring Data JPA – Entity Mapping

§ インタフェースを定義するだけ:• PersonRepositoryの実装は Spring (Data) が提供

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

@Entitypublic class Person {

@Id@GeneratedValue(strategy=GenerationType.AUTO)private BigInteger id;private String firstname, lastname;

@Column(name="email")private String emailAddress;

@OneToManyprivate Set<Person> colleagues;

}

@EnableJpaRepositoriesJavaConfig

XML

Page 8: Spring Data in a Nutshell

88

Spring Data JPA

§ transactional service layer (通常通り)@Servicepublic class DefaultUserManagementService implements UserManagementService {

public PersonRepository personRepository; public ShiftRepository shiftRepository;

@Autowiredpublic DefaultUserManagementService(PersonRepository personRepository,

ShiftRepository shiftRepository) {this.personRepository = personRepository;this.shiftRepository = shiftRepository;

}

@Transactionalpublic void assignToNightShift(String emailAddress) {

Person person = personRepository.findByEmailAddress(emailAddress);

// continue processing

}}

Page 9: Spring Data in a Nutshell

99

Spring Data JPA

§ クエリメソッド(naming conventions ベース)• Query annotation でオーバーライド可能• JPA named query (@NamedQuery) の参照も可.

public interface PersonRepository extends CrudRepository<Person,BigInteger> {

// previous methods omitted…

@Query("select p from Person p where p.emailAddress = ?1")Person findByEmailAddress(String emailAddress);

@Query("select p from Person p where p.firstname = :firstname or p.lastname = :lastname")Person findByLastnameOrFirstname(@Param("lastname") String lastname,

@Param("firstname") String firstname);

}

Page 10: Spring Data in a Nutshell

1010

QueryDSL

§ ”タイプセーフ”な SQL-like なクエリを生成するためのフレームワーク• http://www.querydsl.com/• Open Source, Apache 2.0

§ IDE のコード補完フレンドリー§ 不適切なクエリが構造上不可能(存在しないカラムへのアクセス etc.)§ ドメインのプロパティと型への安全なアクセス(非文字列)

§ Java annotation processor (QueryDSL annotation processor) によるQ<DomainClass> の自動生成

§ Criteria API (JPA 2) より簡潔かつ通常の Java Collection にも使える

private static final QProduct $ = QProduct.product;

macBook = new Product("MacBook Pro", "Apple laptop");iPad = new Product("iPad", "Apple tablet");// …products = Arrays.asList(macBook, iPad, iPod, turntable);

List<Product> result = from($, products).where($.description.contains("Apple")).list($);

Page 11: Spring Data in a Nutshell

1111

QueryDSL - Repositories

§ Repository に QueryDSL interface を拡張(追加)• QueryDSLの Predicate を引数にもつメソッド• JPA, MongoDB

public interface QueryDSLPredicateExecutor<T> {

long count(com.mysema.query.types.Predicate predicate);

T findOne(Predicate predicate);

List<T> findAll(Predicate predicate);

List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);

Page<T> findAll(Predicate predicate, Pageable pageable);}

public interface CustomerRepository extends Repository<Customer, Long>, QueryDslPredicateExecutor<Customer> {

// Your query methods here}

QCustomer customer = QCustomer.customer;LocalDate today = new LocalDate();BooleanExpression customerHasBirthday = customer.birthday.eq(today);BooleanExpression isLongTermCustomer = customer.createdAt.lt(today.minusYears(2));customerRepository.findAll(customerHasBirthday.and(isLongTermCustomer));

Page 12: Spring Data in a Nutshell

1212

MongoDB

§ ドキュメント・データストア

§ ドキュメント == 構造化されたデータ (e.g. XML, JSON)§ JSON スタイルのドキュメント (BSON)

• 基本的に Map、値にプリミティブ/コレクション/ネストのドキュメント型

§ ドキュメントはコレクションというコンテナ(~テーブル)に格納される§ Index サポート –任意の attribute に§ リッチな query language

… 続きは http://www.mongodb.org/ で

{ firstname : "Dave",lastname : "Matthews",addresses : [ { city : "New York", street : "Broadway" } ]

}

Page 13: Spring Data in a Nutshell

1313

MongoDB Java API を使う (1/2)

public void mongoBasic() throws Exception {Mongo mongo = new Mongo();DB db = mongo.getDB("database");DBCollection customers = db.getCollection("customers");

DBObject address = new BasicDBObject("city", ”Kobe");address.put("street", "Broadway");DBObject addresses = new BasicDBList();((BasicDBList) addresses).add(address);DBObject customer = new BasicDBObject("firstname", "Tsuyoshi");customer.put("lastname", "Miyake");customer.put("addresses", addresses);

customers.insert(customer);

System.out.println(customers.findOne());}

}

Page 14: Spring Data in a Nutshell

1414

MongoDB Java API を使う (2/2)

§ Mongo クラスを使用§ サーバに関する詳細は隠蔽される

§ Insert / Update• (全ての)アプリケーション POJO -> DBObjectにマップする必要あり• mongo.getDatabase(…).getCollection(…).insert(…)

§ クエリ• クエリを組み立て、• mongo.getDatabase(…).getCollection(…).find(…)• カーソルを使って結果を iterate• DBObject -> アプリケーション POJO マップ(手動)

è JDBC よりは抽象化されていそうだけど(繰り返しが多い) …

Page 15: Spring Data in a Nutshell

1515

Spring Data MongoDB

§ MongoTemplate• MongoDB特有のオペレーションへのアクセス: geo, map/reduce etc.• Fluent Query, Criteria, Update APIs

§ Object-Document マッピング§ Repository サポート§ Spring XML namespace (e.g. <mongo:XXX>)§ QueryDSLサポート§ JMX / Logging

Page 16: Spring Data in a Nutshell

1616

Spring Data MongoDB – Entity Mapping (1/3)

@Documentpublic class Customer {

@Idprivate BigInteger id;private String firstname, lastname;

@Field("email")@Indexed(unique = true)private EmailAddress emailAddress;private Set<Address> addresses = new HashSet<Address>();

public Customer(String firstname, String lastname) {Assert.hasText(firstname);Assert.hasText(lastname);

this.firstname = firstname;this.lastname = lastname;

}…}

Page 17: Spring Data in a Nutshell

1717

Spring Data MongoDB – Entity Mapping (2/3)public final class EmailAddress {

private static final String EMAIL_REGEX = “…";private static final Pattern PATTERN = Pattern.compile(EMAIL_REGEX);

@Field("email")private final String value;

public EmailAddress(String emailAddress) {Assert.isTrue(isValid(emailAddress), "Invalid email address!");this.value = emailAddress;

}… }

public class Address {private final String street, city, country;

public Address(String street, String city, String country) {Assert.hasText(street, "Street must not be null or empty!");…

this.street = street;this.city = city;this.country = country;

}… }

Page 18: Spring Data in a Nutshell

1818

Spring Data MongoDB – Entity Mapping (3/3)public void mongoSpring() throws Exception {

MongoMappingContext context = new MongoMappingContext();MongoDbFactory dbFactory = new SimpleMongoDbFactory(new Mongo(),

"database");MappingMongoConverter converter = new MappingMongoConverter(dbFactory,

context);Customer customer = new Customer("Tsuyoshi", "Miyake");customer.setEmailAddress(new EmailAddress("[email protected]"));customer.add(new Address("Minato-ku", "Tokyo", "Japan"));DBObject sink = new BasicDBObject();converter.write(customer, sink);System.out.println(sink.toString());

}

{ "_class" : "com.oreilly.springdata.mongodb.core.Customer”, "_id" : null ,"firstname" : "Tsuyoshi" ,"lastname" : "Miyake" ,"email" : { "email" : "[email protected]"} ,"addresses" : [ { "street" : "Minato-ku" , "city" : "Tokyo" , "country" : "Japan"}]}

Page 19: Spring Data in a Nutshell

1919

Spring Data Mongo – MongoTemplate使用法@AutowiredMongoTemplate template; // in AbstractMongoConfiguration (JavaConfig)

@Testpublic void mongoTemplate() throws Exception {

Customer customer = new Customer("Kirari", "Miyake");customer.setEmailAddress(new EmailAddress("[email protected]"));template.save(customer);

Query query = new Query(new

Criteria("emailAddress").is("[email protected]"));assertThat(template.findOne(query, Customer.class), is(customer));

}@Configuration@ComponentScan@EnableMongoRepositoriesclass ApplicationConfig extends AbstractMongoConfiguration {

@Overrideprotected String getDatabaseName() { return ”database”; }

@Overridepublic Mongo mongo() throws Exception {…}

… }

Page 20: Spring Data in a Nutshell

2020

Spring Data Mongo - Repositories

§ Spring Data Commons の Repository 同様• インタフェースの定義(のみ) & naming convention

Page 21: Spring Data in a Nutshell

2121

Spring Data Mongo – Repository 使用法

or @EnableMongoRepositories in JavaConfig

Page 22: Spring Data in a Nutshell

2222

Neo4j

§ グラフデータベース

§ DB はグラフのノード (nodes) と関連 (relationships) から成る• Nodes と relationships はプロパティーをもつ

§ Cypher Query Language § Indexes on node/relationship プロパティー§ Java で記述されている、アプリケーションへ組み込み可能• Also a REST API (Neo4j Server)

§ Transactional (ACID)

… 続きは http://neo4j.org/ で

Page 23: Spring Data in a Nutshell

2323

Neo4j データモデル

Page 24: Spring Data in a Nutshell

2424

Spring Data Neo4j

§ Neo4jTemplate• Neo4j 特有のオペレーションへのアクセス: get/create Node and Relationship,

query, traverse, fluent query Result handling• トランザクション管理• Exception translation to Spring’s DAO exception hierarchy• Also works via REST with Neo4jServer

§ アノテーションベースの Entity 定義(@NodeEntity/@RelationshipEntity..)§ Repository サポート§ Cypher query language§ Spring XML namespace (<neo4j:XXX>)§ Neo4j Server 統合

<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase”

/>

Page 25: Spring Data in a Nutshell

2525

Classic Neo4j – Entity class

public class Person {

private final Node underlyingNode;

public Person(final Node node) {underlyingNode = node;

}

public Node getUnderlyingNode() {return underlyingNode;

}

public final String getName() {return (String) underlyingNode.getProperty(“name”);

}

public void setName(final String name) {underlyingNode.setProperty(“name”, name);

} }

Page 26: Spring Data in a Nutshell

2626

Spring Data Neo4j – Entity class

@NodeEntitypublic class Actor {

@Indexed // Neo4jTemplate.getOrCreateNode() etc. で利用可能private String id;

@Indexed(indexType=IndexType.FULLTEXT , indexName=“people")private String name;

public Person(String id, String name) {this.id = id;this.name = name;

}

public String getId() { return id; }

public String getName() { return name; }

public void setName(String name) { this.name = name; } }

Page 27: Spring Data in a Nutshell

2727

Spring Data Neo4j – Entity class

@NodeEntitypublic class Movie {

@Indexedprivate String id;

@Indexed(indexType=IndexType.FULLTEXT , indexName=“search")private String title;

// Collection of other nodes@RelatedTo(type = "ACTS_IN", direction= INCOMING)private Set<Actor> actors;

// Collection of relationships (actor -> (rating) -> movie)@RelatedToVia(type = “RATED", direction= INCOMING)private Set<Rating> rating;

public Movie(String id, String title) {this.id = id;this.title = title;

}

// Getters and Setters omitted}

Page 28: Spring Data in a Nutshell

2828

Spring Data Neo4j - Repositories

§ Spring Data Commons の Repository 同様• インタフェースの定義(のみ) & naming convention

§ Support for• CRUD• IndexRepository (findAllByPropertyValue, findAllByQuery etc.)• TraversalRepository (findAllByTraversal)

public interface MovieRepository extends GraphRepository<Movie>, NamedIndexRepository<Movie>, RelationshipOperationsRepository<Movie> {

Movie findById(String id);Page<Movie> findByTitleLike(String title, Pageable page);@Query("start user=node({0}) " +

" match user-[r:RATED]->movie<-[r2:RATED]-other-[r3:RATED]->otherMovie " +" where r.stars >= 3 and r2.stars >= 3 and r3.stars >= 3 " +" return otherMovie, avg(r3.stars) " +" order by avg(r3.stars) desc, count(*) desc" +" limit 10")

List<MovieRecommendation> getRecommendations(User user);}

<neo4j:repositories base-package="org.neo4j.cineasts.repository"/>

Page 29: Spring Data in a Nutshell

2929

Spring Data Neo4j – Neo4jTemplate

public void setUp() throws Exception {dave = template.save(new Customer("Dave", "Matthews", "[email protected]"));template.save(new Customer("Carter","Beauford","[email protected]"));template.save(new Customer("Boyd","Tinsley","[email protected]"));final Country usa = template.save(new Country("US", "United States"));template.save(new Address("27 Broadway","New York",usa));iPad = template.save(new Product("iPad", "Apple tablet device")

.withPrice(BigDecimal.valueOf(499D)));mbp = template.save(new Product("MacBook Pro", "Apple notebook").withPrice(BigDecimal.valueOf(1299D)));

final Order order = new Order(dave);order.add(iPad,2);order.add(mbp,1);template.save(order);

}

Page 30: Spring Data in a Nutshell

3030

Redis

§ Advanced key-value store•軽量 & 高パフォーマンス (in-memory)• Values: binary strings, Lists, Sets, Ordered Sets, Hash maps, ..• データタイプごとの操作: e.g. list への追加 ([RL]PUSH), set への追加

(SADD), retrieving a slice of a list (LRANGE key start end), …•各操作がアトミック (e.g. INCR)

§ Very fast: ~100K operations/second on entry-level hardware§ 永続化対応

• Periodic snapshots (point-in-time)• Write コマンドのログファイルへの書き出し (append-based)

§ PUB/SUB§ トランザクション対応 (MULTI <-> EXEC)§ 多言語対応, all separate open source projects

… 続きは http://redis.io/ で

K1

K2

K3

V1

V2

V2

Page 31: Spring Data in a Nutshell

3131

Spring Data Redis

§ Redis ドライバに依存しない統一された API を提供§ RedisTemplate

• Redisの機能実装。各データタイプごとに専用のインタフェース• Value/Hash/Set/Zset/ListOperations• 名前は分かりやすいように変換: SETNX -> putIfAbsent()

• 自動で serialization と型変換を実施• Fluent query API

§ 非同期 Publish-Subscribe サポート with message listener containers§ JDK Atomic counters (AtomicLong etc.) backed by Redis§ Spring 3.1 Cache abstraction provider

Page 32: Spring Data in a Nutshell

3232

Spring Data Redis – RedisTemplate –型変換

<bean id="conFactory“ class="o.s.d.r.connection.jedis.JedisConnectionFactory"/><bean id=“template“ class="o.s.d.redis.core.StringRedisTemplate"

p:connection-factory-ref="conFactory"/>

@Beanpublic RedisTemplate<String, Long> longTemplate() {

RedisTemplate<String, Long> tmpl = new RedisTemplate<String, Long>();tmpl.setConnectionFactory( redisConnectionFactory() );tmpl.setValueSerializer(LongSerializer.INSTANCE);return tmpl;

}

public static enum LongSerializer implements RedisSerializer<Long> {INSTANCE;@Override public byte[] serialize( Long aLong ) throws SerializationException {

if ( null != aLong ) { return aLong.toString().getBytes(); }else { return new byte[0]; }

}

@Override public Long deserialize( byte[] bytes ) throws SerializationException {if ( bytes.length > 0 ) {

return Long.parseLong( new String( bytes ) );} else { return null; }

}}

Page 33: Spring Data in a Nutshell

3333

Spring Data Redis – RedisTemplate – アトミック操作

@Autowired RedisConnectionFactory connectionFactory;

@Test public void testAtomicCounters() {RedisAtomicLong counter = new RedisAtomicLong("spring-data-book:counter-

test:hits", connectionFactory, 0);Long l = counter.incrementAndGet();

assertThat(l, is(greaterThan(0L)));}

Page 34: Spring Data in a Nutshell

3434

Spring Data Redis – RedisTemplate – Pub/Sub

@Configurationpublic class PubSubConfig extends ApplicationConfig {public static final String DUMP_CHANNEL = ”pubsub-test:dump";

@Bean RedisMessageListenerContainer container() {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(redisConnectionFactory());container.addMessageListener(dumpToConsoleListener(), new ChannelTopic(DUMP_CHANNEL));return container;

}

@Bean MessageListener dumpToConsoleListener() {return new MessageListener() {@Override public void onMessage(Message message, byte[] pattern) {System.out.println("FROM MESSAGE: " + new String(message.getBody()));

}};

}}

@Test public void testPubSubWithoutConversion() {RedisConnection redis = connectionFactory.getConnection();try {redis.publish( PubSubConfig.DUMP_CHANNEL.getBytes(), "Hello World!".getBytes() );

} finally { redis.close(); }}

Page 35: Spring Data in a Nutshell

3535

• 分散/メモリーベースのデータ管理プラットフォーム

• データトランザクションの多いアプリケーションに対し、可用性、高パフォーマンス、スケーラビリティを提供

• データの一貫性を場合に応じて調節可能(分散ロックのレベル)

• イベントドリブンなアーキテクチャ

… 続きはhttp://www.vmware.com/support/pubs/vfabric-gemfire.html で

GemFire – The Enterprise Data Fabric

JavaClient

C#Client

C++Client

Page 36: Spring Data in a Nutshell

3636

GemFire High Level アーキテクチャJavaClient

C#Client

C++Client クライアントは Cache を組

み込み可能 (with disk overflow)

物理的なサーバー群がひとつの

巨大な論理システムとしてみえる (DistributedSystem)

オブジェクトの変更がサブスクライバに伝達される

同期 R/W、非同期Write

データのパーティショニン

グ・レプリケーションはクライアントからは透過的に扱われる。

また、ストレージにメモリデータをバックアップ可能

動的にノードを追加可能

Page 37: Spring Data in a Nutshell

3737

• Cache がインメモリのストレージ、およびデータ管理を提供 (RDBMS でいうところの Database)

• XML (cache.xml) and/or API calls の組合せでCache を構成

• 複数の Regions から構成される

Cache / Region

z

Application

Region

Region

Region

Cache

Cache

• Region class は java.util.Map interface を実装• データの保存方法 (Replicated/Partition)や場所に依らず一貫した API を提供

• Region 内でキーは一意である必要がある Region

java.util.Map

Region

Page 38: Spring Data in a Nutshell

3838

• クライアントが distributed system に接続する方法としてGemFire server に(直接)、または “locator” 経由で接続する方法がある

• クライアントは独自にサーバーからのデータをローカルにコピー(キャッシュ)することが可能

• クライアントはサーバー側の変更に対し register 可能。その場合変更があった際にクライアントに通知されるようになる

Client Cache

Application

Application

Region

Region

Region

Cache

Client Cache

Page 39: Spring Data in a Nutshell

3939

• GemFire distributed system に接続、および Cache を生成するプロセス• Locator• Cacheserver (Cache 保持)• Agent

• 最小構成の GemFire プロセスは組み込みモードで実行される単一のノード

メンバー構成

Application

Region

Region

RegionCache

Application

Region

Region

RegionCache

Application

Region

Region

RegionCache

Application ApplicationApplication

Page 40: Spring Data in a Nutshell

4040

GemFire Topologies

Embedded

Peer-To-Peer

Client/Server

Multi-site/WAN Gateway

Topologies of GemFire

Page 41: Spring Data in a Nutshell

4141

Application

Region

Region

RegionCache

Application

Region

Region

RegionCache

Application

Region

Region

RegionCache

Topologies – Embedded / Peer to Peer

Application

Region

Region

RegionCache

Page 42: Spring Data in a Nutshell

4242

Topologies – Client-Server

ApplicationApplicationApplication

Application

Region

Region

Region

Cache

Application

Region

Region

Region

Cache

Application

Region

Region

Region

Cache

Page 43: Spring Data in a Nutshell

4343

Creating a Cache - XML

Application

Region

Cache

<?xml version="1.0"?><!DOCTYPE cache PUBLIC

"-//GemStone Systems, Inc.//GemFire Declarative Caching 6.6//EN"

"http://www.gemstone.com/dtd/cache6_6.dtd"><cache>

<region name="Customer” refid="REPLICATE" /></cache>

cache.xml

Load XML via JavaCache cache = new CacheFactory()

.set("cache-xml-file", "xml/cache.xml")

.create();Region<Integer, Customer> customers = cache.getRegion("Customer");

Page 44: Spring Data in a Nutshell

4444

Creating a Cache - API

Application

Region

Cache

// Create the cache without using a cache xml fileCache cache = new CacheFactory().create();

// Create a region dynamically using the APIsRegion<Integer, Customer> customers =

(Region<Integer, Customer>)cache.createRegionFactory().create("Customer”);

§ Classes in com.gemstone.gemfire.cache

§ Call cache.close() when done

Page 45: Spring Data in a Nutshell

4545

In gemfire.properties:

Setting startup parameters

log-level=warning

statistic-sampling-enabled=true

statistic-sample-rate=100

statistic-archive-file=/Users/myMac/myApp/stats1007.gfs

locators=localhost[41111],….

mcast-port=0

cache-xml-file=myCache.xml

§ 起動時に読み込まれる構成ファイル§ cache-xml を指定も可能

Page 46: Spring Data in a Nutshell

4646

Spring Data Gemfire

§ Spring namespace (gfe) を用いた Gemfireの構成§ cache.xml との比較

• Import, property placeholder, SpEL etc.

§ Declarative Transaction Management• gfe:transaction-manager -> region 操作が atomic に

§ Exception translation§ GemFireTemplate

• Connection/Transaction 管理の自動化• GemFire native APIにアクセス可能

§ Entity / PDX Mapping§ Repository サポート

Page 47: Spring Data in a Nutshell

4747

Spring Data Gemfire - Configuration

<gfe:cache /> // id=“gemfireCache”

<gfe:replicated-region id="simple" />

<gfe:partitioned-region id="complex" local-max-memory="20"><gfe:cache-listener>

<ref bean="c-listener"/><bean class="org.springframework.data.gemfire.SimpleCacheListener"/>

</gfe:cache-listener><gfe:cache-loader ref="c-loader"/><gfe:cache-writer ref="c-writer"/>

</gfe:partitioned-region>

<bean id="c-listener" class="org.springframework.data.gemfire.SimpleCacheListener"/><bean id="c-loader" class="org.springframework.data.gemfire.SimpleCacheLoader"/><bean id="c-writer" class="org.springframework.data.gemfire.SimpleCacheWriter"/>

§ 標準の Spring 機能 (property replacement, environment) を利用可能

Page 48: Spring Data in a Nutshell

4848

Spring Data Gemfire – Entity Mapping

@Region("myRegion")public class Person {

@Id BigInteger id; // Cache キー@Indexed String firstname;

@Transient String middleName; // persist されない

@PersistenceConstructor // コンストラクタの明示指定public Person(String firstname, String lastname) { … }

}

Page 49: Spring Data in a Nutshell

4949

Spring Data Gemfire - Repositories

interface PersonRepository extends CrudRepository<Person, BigInteger> {

// Finder for a single entityPerson findByEmailAddress(String emailAddress);

// Finder for multiple entitiesList<Person> findByLastnameLike(String lastname);

// Finder with manually defined query@Query("SELECT p FROM /Person p WHERE p.firstname = $1")List<Person> findByFirstname(String firstname);

}

Page 50: Spring Data in a Nutshell

5050

Spring Data Gemfire – Repositories<gf:repositories base-package="com.acme.repositories"/>

@Service

public class MySimpleService {@Autowired PersonRepository personRepository;

@Autowired AccountRepository accountRepository;

@Transactional

public List<Person> doSomething(Integer personId) {Person person = personRepository.findOne(personId);

List<Person> persons = accountRepository.findByPerson(person);}

}

public interface PersonRepository extends CrudRepository<Person, BigInteger> {

// Finder for a single entityPerson findByEmailAddress(String emailAddress);

// Finder for multiple entitiesList<Person> findByLastnameLike(String lastname);

// Finder with manually defined query (OQL)

@Query("SELECT p FROM /Person p WHERE p.firstname = $1")List<Person> findByFirstname(String firstname);

}

Page 51: Spring Data in a Nutshell

5151

Thank you!Q&A

@tsuyokb