SlideShare a Scribd company logo
© 2012 SpringSource, A division of VMware. All rights reserved
Spring Data in a Nutshell
Tsuyoshi Miyake (@tsuyokb)
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 をなくす
• 異なるテクノロジーをまたがって利用できる共通のインタフェース
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
44
Spring Data Repositories (1/3)
public interface CrudRepository<T, ID extends Serializable> extends
Repository<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>
}
55
Spring Data Repositories (2/3)
public interface PagingAndSortingRepository<T, ID extends Serializable> extends
CrudRepository<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 entity
Person findByEmailAddress(String emailAddress);
// Finder for a multiple entities
List<Person> findByLastnameLike(String lastName);
// Finder with pagination
Page<Person> findByFirstnameLike(String firstName, Pageable page);
}
66
Spring Data Repositories (3/3)
@NoRepositoryBean
public 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 のベースに
77
Spring Data JPA – Entity Mapping
§ インタフェースを定義するだけ:
• PersonRepository の実装は Spring (Data) が提供
<jpa:repositories base-package="com.acme.repository" />
@Entity
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private BigInteger id;
private String firstname, lastname;
@Column(name="email")
private String emailAddress;
@OneToMany
private Set<Person> colleagues;
}
@EnableJpaRepositoriesJavaConfig
XML
88
Spring Data JPA
§ transactional service layer (通常通り)
@Service
public class DefaultUserManagementService implements UserManagementService {
public PersonRepository personRepository;
public ShiftRepository shiftRepository;
@Autowired
public DefaultUserManagementService(PersonRepository personRepository,
ShiftRepository shiftRepository) {
this.personRepository = personRepository;
this.shiftRepository = shiftRepository;
}
@Transactional
public void assignToNightShift(String emailAddress) {
Person person = personRepository.findByEmailAddress(emailAddress);
// continue processing
}
}
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);
}
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($);
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));
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" } ]
}
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());
}
}
1414
MongoDB Java API を使う (2/2)
§ Mongo クラスを使用
§ サーバに関する詳細は隠蔽される
§ Insert / Update
• (全ての)アプリケーション POJO -> DBObject にマップする必要あり
• mongo.getDatabase(…).getCollection(…).insert(…)
§ クエリ
• クエリを組み立て、
• mongo.getDatabase(…).getCollection(…).find(…)
• カーソルを使って結果を iterate
• DBObject -> アプリケーション POJO マップ(手動)
è JDBC よりは抽象化されていそうだけど(繰り返しが多い) …
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
1616
Spring Data MongoDB – Entity Mapping (1/3)
@Document
public class Customer {
@Id
private 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;
}
…
}
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;
}
… }
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("tmiyake@vmware.com"));
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" : "tmiyake@vmware.com"} ,
"addresses" : [ { "street" : "Minato-ku" , "city" : "Tokyo" , "country" : "Japan"}]}
1919
Spring Data Mongo – MongoTemplate 使用法
@Autowired
MongoTemplate template; // in AbstractMongoConfiguration (JavaConfig)
@Test
public void mongoTemplate() throws Exception {
Customer customer = new Customer("Kirari", "Miyake");
customer.setEmailAddress(new EmailAddress("kirari.miyake@gmail.com"));
template.save(customer);
Query query = new Query(
new
Criteria("emailAddress").is("kirari.miyake@gmail.com"));
assertThat(template.findOne(query, Customer.class), is(customer));
}
@Configuration
@ComponentScan
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() { return ”database”; }
@Override
public Mongo mongo() throws Exception {…}
… }
2020
Spring Data Mongo - Repositories
§ Spring Data Commons の Repository 同様
• インタフェースの定義(のみ) & naming convention
2121
Spring Data Mongo – Repository 使用法
or @EnableMongoRepositories in JavaConfig
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/ で
2323
Neo4j データモデル
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”
/>
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);
}
}
2626
Spring Data Neo4j – Entity class
@NodeEntity
public 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; }
}
2727
Spring Data Neo4j – Entity class
@NodeEntity
public class Movie {
@Indexed
private 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
}
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"/>
2929
Spring Data Neo4j – Neo4jTemplate
public void setUp() throws Exception {
dave = template.save(new Customer("Dave", "Matthews", "dave@dmband.com"));
template.save(new Customer("Carter","Beauford","carter@dmband.com"));
template.save(new Customer("Boyd","Tinsley","boyd@dmband.com"));
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);
}
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
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
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"/>
@Bean
public 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; }
}
}
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)));
}
3434
Spring Data Redis – RedisTemplate – Pub/Sub
@Configuration
public 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(); }
}
3535
• 分散/メモリーベースのデータ管理プラットフォ
ーム
• データトランザクションの多いアプリケーション
に対し、可用性、高パフォーマンス、スケーラビ
リティを提供
• データの一貫性を場合に応じて調節可能(分散
ロックのレベル)
• イベントドリブンなアーキテクチャ
… 続きは
http://www.vmware.com/support/pubs/vfabri
c-gemfire.html で
GemFire – The Enterprise Data Fabric
Java
Client
C#
Client
C++
Client
3636
GemFire High Level アーキテクチャ
Java
Client
C#
Client
C++
Client クライアントは Cache を組
み込み可能 (with disk
overflow)
物理的なサーバー群がひとつの
巨大な論理システムとしてみえ
る (DistributedSystem)
オブジェクトの変更がサブス
クライバに伝達される
同期 R/W、非同期 Write
データのパーティショニン
グ・レプリケーションはクライ
アントからは透過的に扱わ
れる。
また、ストレージにメモリデ
ータをバックアップ可能
動的にノードを追加可能
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
3838
• クライアントが distributed system に接続する方法としてGemFire server に(直接)、
または “locator” 経由で接続する方法がある
• クライアントは独自にサーバーからのデータをローカルにコピー(キャッシュ)すること
が可能
• クライアントはサーバー側の変更に対し register 可能。その場合変更があった際にク
ライアントに通知されるようになる
Client Cache
Application
Application
Region
Region
Region
Cache
Client Cache
3939
• GemFire distributed system に接続、および Cache を生成するプロセス
• Locator
• Cacheserver (Cache 保持)
• Agent
• 最小構成の GemFire プロセスは組み込みモードで実行される単一のノード
メンバー構成
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
Application ApplicationApplication
4040
GemFire Topologies
Embedded
Peer-To-Peer
Client/Server
Multi-site/WAN Gateway
Topologies of GemFire
4141
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
Topologies – Embedded / Peer to Peer
Application
Region
Region
Region
Cache
4242
Topologies – Client-Server
ApplicationApplicationApplication
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
Application
Region
Region
Region
Cache
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 Java
Cache cache = new CacheFactory()
.set("cache-xml-file", "xml/cache.xml")
.create();
Region<Integer, Customer> customers = cache.getRegion("Customer");
4444
Creating a Cache - API
Application
Region
Cache
// Create the cache without using a cache xml file
Cache cache = new CacheFactory().create();
// Create a region dynamically using the APIs
Region<Integer, Customer> customers =
(Region<Integer, Customer>)cache.createRegionFactory()
.create("Customer”);
§ Classes in
com.gemstone.gemfire.cache
§ Call cache.close() when done
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 を指定も可能
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 サポート
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) を利用可能
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) { … }
}
4949
Spring Data Gemfire - Repositories
interface PersonRepository extends CrudRepository<Person, BigInteger> {
// Finder for a single entity
Person findByEmailAddress(String emailAddress);
// Finder for multiple entities
List<Person> findByLastnameLike(String lastname);
// Finder with manually defined query
@Query("SELECT p FROM /Person p WHERE p.firstname = $1")
List<Person> findByFirstname(String firstname);
}
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 entity
Person findByEmailAddress(String emailAddress);
// Finder for multiple entities
List<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);
}
5151
Thank you!
Q&A
@tsuyokb

More Related Content

PPTX
BPStudy32 CouchDB 再入門
KEY
はじめてのCouch db
PDF
Html5 Web Applications
PPTX
FIWARE Context Information Management
PDF
事例で学ぶトレジャーデータ 20140612
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.3.0対応)
PPTX
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.3.0対応)
ZIP
負荷テストことはじめ
BPStudy32 CouchDB 再入門
はじめてのCouch db
Html5 Web Applications
FIWARE Context Information Management
事例で学ぶトレジャーデータ 20140612
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.3.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.3.0対応)
負荷テストことはじめ

What's hot (20)

PPTX
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
PPTX
Active Directoryデータのプロパティ出力(Output Properties)
PDF
Javaでmongo db
PDF
Html5j data visualization_and_d3
PPTX
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.4.0対応)
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 2.4.0対応)
PPTX
Active Directoryデータの "大きい整数"
PPTX
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.6.0対応)
PDF
Pro aspnetmvc3framework chap19
PDF
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.2.0対応)
PDF
jQuery超入門編
PPTX
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.1.0対応)
PDF
Xslt
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.4.0対応)
PPTX
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.5.0対応)
PDF
AndroidでActiveRecordライクにDBを使う
PDF
Parse introduction
PPTX
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.1.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
Active Directoryデータのプロパティ出力(Output Properties)
Javaでmongo db
Html5j data visualization_and_d3
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.4.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 2.4.0対応)
Active Directoryデータの "大きい整数"
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.0.0対応)
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.6.0対応)
Pro aspnetmvc3framework chap19
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.2.0対応)
jQuery超入門編
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.1.0対応)
Xslt
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.4.0対応)
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.5.0対応)
AndroidでActiveRecordライクにDBを使う
Parse introduction
FIWARE Orion Context Broker コンテキスト情報管理 (Orion 3.1.0対応)
Ad

Viewers also liked (14)

PDF
Cloudera + MicrosoftでHadoopするのがイイらしい。 #CWT2016
PDF
Cloudera Data Science WorkbenchとPySparkで 好きなPythonライブラリを 分散で使う #cadeda
PDF
Spring Cloud in a Nutshell
PDF
Cloudera in the Cloud #CWT2017
PDF
クラウド時代の Spring Framework (aka Spring Framework in Cloud Era)
PDF
#cwt2016 Apache Kudu 構成とテーブル設計
PPTX
Hue 4.0 / Hue Meetup Tokyo #huejp
PDF
Cloud Native Hadoop #cwt2016
PDF
先行事例から学ぶ IoT / ビッグデータの始め方
PPTX
Clouderaが提供するエンタープライズ向け運用、データ管理ツールの使い方 #CW2017
PDF
How to go into production your machine learning models? #CWT2017
PDF
Apache Kuduは何がそんなに「速い」DBなのか? #dbts2017
PDF
Apache Kudu - Updatable Analytical Storage #rakutentech
PDF
大規模データに対するデータサイエンスの進め方 #CWT2016
Cloudera + MicrosoftでHadoopするのがイイらしい。 #CWT2016
Cloudera Data Science WorkbenchとPySparkで 好きなPythonライブラリを 分散で使う #cadeda
Spring Cloud in a Nutshell
Cloudera in the Cloud #CWT2017
クラウド時代の Spring Framework (aka Spring Framework in Cloud Era)
#cwt2016 Apache Kudu 構成とテーブル設計
Hue 4.0 / Hue Meetup Tokyo #huejp
Cloud Native Hadoop #cwt2016
先行事例から学ぶ IoT / ビッグデータの始め方
Clouderaが提供するエンタープライズ向け運用、データ管理ツールの使い方 #CW2017
How to go into production your machine learning models? #CWT2017
Apache Kuduは何がそんなに「速い」DBなのか? #dbts2017
Apache Kudu - Updatable Analytical Storage #rakutentech
大規模データに対するデータサイエンスの進め方 #CWT2016
Ad

Similar to Spring Data in a Nutshell (20)

PPT
Gaej Jdo
PPT
Spring3.1概要 データアクセスとトランザクション処理
PDF
金魚本読書ノート JPA編
PDF
20181031 springfest spring data geode
PPT
JPA説明会
PDF
REST with Spring Boot #jqfk
PPTX
Beginning Java EE 6 勉強会(2) #bje_study
PDF
Cassandraとh baseの比較して入門するno sql
PDF
Getting started MySQL as Document Data Store
PPTX
Spring data-rest-and-spring-cloud-contract
PPTX
Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで
PDF
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
PPTX
はじめてのJPA
ODP
Spring2概論@第1回JSUG勉強会
PDF
SpringOneでの3⽇間とSpring 5.1最新情報
PDF
JJUG CCC 2017 Spring LT about JPA
PDF
Introduction to MongoDB
PDF
クラウド・アプリケーション・モデリングへのアプローチ
PDF
MongoDB勉強会資料
PDF
Core Data の概要と NSIncrementalStore
Gaej Jdo
Spring3.1概要 データアクセスとトランザクション処理
金魚本読書ノート JPA編
20181031 springfest spring data geode
JPA説明会
REST with Spring Boot #jqfk
Beginning Java EE 6 勉強会(2) #bje_study
Cassandraとh baseの比較して入門するno sql
Getting started MySQL as Document Data Store
Spring data-rest-and-spring-cloud-contract
Neo4j の「データ操作プログラミング」から 「ビジュアライズ」まで
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
はじめてのJPA
Spring2概論@第1回JSUG勉強会
SpringOneでの3⽇間とSpring 5.1最新情報
JJUG CCC 2017 Spring LT about JPA
Introduction to MongoDB
クラウド・アプリケーション・モデリングへのアプローチ
MongoDB勉強会資料
Core Data の概要と NSIncrementalStore

More from Tsuyoshi Miyake (19)

PDF
猿でもわかる DevOps
PDF
はじめての JFrog Platform V2
PDF
はじめての JFrog Distribution
PDF
はじめての JFrog Pipelines
PDF
はじめての JFrog Xray
PDF
はじめての JFrog Artifactory
PDF
はじめての JFrog Platform
PDF
猿でもわかる Helm
PDF
Artifact Driven CI/CD
PDF
猿でもわかるサーバーレス
PDF
Java 開発者のための次世代 DevOps: BinOps
PDF
カエルと実践するコンテナ
PDF
猿でもわかるコンテナ・オーケストレーション
PDF
猿でもわかるコンテナ
PDF
カエルと実践する CI/CD CD 編
PDF
カエルと実践する CI/CD CI 編
PDF
猿でもわかる CI/CD
PDF
カエルと実践するバイナリ・リポジトリマネージャー
PDF
猿でもわかるバイナリ・リポジトリマネージャー
猿でもわかる DevOps
はじめての JFrog Platform V2
はじめての JFrog Distribution
はじめての JFrog Pipelines
はじめての JFrog Xray
はじめての JFrog Artifactory
はじめての JFrog Platform
猿でもわかる Helm
Artifact Driven CI/CD
猿でもわかるサーバーレス
Java 開発者のための次世代 DevOps: BinOps
カエルと実践するコンテナ
猿でもわかるコンテナ・オーケストレーション
猿でもわかるコンテナ
カエルと実践する CI/CD CD 編
カエルと実践する CI/CD CI 編
猿でもわかる CI/CD
カエルと実践するバイナリ・リポジトリマネージャー
猿でもわかるバイナリ・リポジトリマネージャー

Spring Data in a Nutshell

  • 1. © 2012 SpringSource, A division of VMware. All rights reserved Spring Data in a Nutshell Tsuyoshi Miyake (@tsuyokb)
  • 2. 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 をなくす • 異なるテクノロジーをまたがって利用できる共通のインタフェース
  • 3. 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
  • 4. 44 Spring Data Repositories (1/3) public interface CrudRepository<T, ID extends Serializable> extends Repository<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> }
  • 5. 55 Spring Data Repositories (2/3) public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<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 entity Person findByEmailAddress(String emailAddress); // Finder for a multiple entities List<Person> findByLastnameLike(String lastName); // Finder with pagination Page<Person> findByFirstnameLike(String firstName, Pageable page); }
  • 6. 66 Spring Data Repositories (3/3) @NoRepositoryBean public 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 のベースに
  • 7. 77 Spring Data JPA – Entity Mapping § インタフェースを定義するだけ: • PersonRepository の実装は Spring (Data) が提供 <jpa:repositories base-package="com.acme.repository" /> @Entity public class Person { @Id @GeneratedValue(strategy=GenerationType.AUTO) private BigInteger id; private String firstname, lastname; @Column(name="email") private String emailAddress; @OneToMany private Set<Person> colleagues; } @EnableJpaRepositoriesJavaConfig XML
  • 8. 88 Spring Data JPA § transactional service layer (通常通り) @Service public class DefaultUserManagementService implements UserManagementService { public PersonRepository personRepository; public ShiftRepository shiftRepository; @Autowired public DefaultUserManagementService(PersonRepository personRepository, ShiftRepository shiftRepository) { this.personRepository = personRepository; this.shiftRepository = shiftRepository; } @Transactional public void assignToNightShift(String emailAddress) { Person person = personRepository.findByEmailAddress(emailAddress); // continue processing } }
  • 9. 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); }
  • 10. 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($);
  • 11. 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));
  • 12. 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" } ] }
  • 13. 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()); } }
  • 14. 1414 MongoDB Java API を使う (2/2) § Mongo クラスを使用 § サーバに関する詳細は隠蔽される § Insert / Update • (全ての)アプリケーション POJO -> DBObject にマップする必要あり • mongo.getDatabase(…).getCollection(…).insert(…) § クエリ • クエリを組み立て、 • mongo.getDatabase(…).getCollection(…).find(…) • カーソルを使って結果を iterate • DBObject -> アプリケーション POJO マップ(手動) è JDBC よりは抽象化されていそうだけど(繰り返しが多い) …
  • 15. 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
  • 16. 1616 Spring Data MongoDB – Entity Mapping (1/3) @Document public class Customer { @Id private 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; } … }
  • 17. 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; } … }
  • 18. 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("tmiyake@vmware.com")); 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" : "tmiyake@vmware.com"} , "addresses" : [ { "street" : "Minato-ku" , "city" : "Tokyo" , "country" : "Japan"}]}
  • 19. 1919 Spring Data Mongo – MongoTemplate 使用法 @Autowired MongoTemplate template; // in AbstractMongoConfiguration (JavaConfig) @Test public void mongoTemplate() throws Exception { Customer customer = new Customer("Kirari", "Miyake"); customer.setEmailAddress(new EmailAddress("kirari.miyake@gmail.com")); template.save(customer); Query query = new Query( new Criteria("emailAddress").is("kirari.miyake@gmail.com")); assertThat(template.findOne(query, Customer.class), is(customer)); } @Configuration @ComponentScan @EnableMongoRepositories class ApplicationConfig extends AbstractMongoConfiguration { @Override protected String getDatabaseName() { return ”database”; } @Override public Mongo mongo() throws Exception {…} … }
  • 20. 2020 Spring Data Mongo - Repositories § Spring Data Commons の Repository 同様 • インタフェースの定義(のみ) & naming convention
  • 21. 2121 Spring Data Mongo – Repository 使用法 or @EnableMongoRepositories in JavaConfig
  • 22. 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/ で
  • 24. 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” />
  • 25. 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); } }
  • 26. 2626 Spring Data Neo4j – Entity class @NodeEntity public 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; } }
  • 27. 2727 Spring Data Neo4j – Entity class @NodeEntity public class Movie { @Indexed private 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 }
  • 28. 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"/>
  • 29. 2929 Spring Data Neo4j – Neo4jTemplate public void setUp() throws Exception { dave = template.save(new Customer("Dave", "Matthews", "dave@dmband.com")); template.save(new Customer("Carter","Beauford","carter@dmband.com")); template.save(new Customer("Boyd","Tinsley","boyd@dmband.com")); 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); }
  • 30. 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
  • 31. 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
  • 32. 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"/> @Bean public 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; } } }
  • 33. 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))); }
  • 34. 3434 Spring Data Redis – RedisTemplate – Pub/Sub @Configuration public 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(); } }
  • 35. 3535 • 分散/メモリーベースのデータ管理プラットフォ ーム • データトランザクションの多いアプリケーション に対し、可用性、高パフォーマンス、スケーラビ リティを提供 • データの一貫性を場合に応じて調節可能(分散 ロックのレベル) • イベントドリブンなアーキテクチャ … 続きは http://www.vmware.com/support/pubs/vfabri c-gemfire.html で GemFire – The Enterprise Data Fabric Java Client C# Client C++ Client
  • 36. 3636 GemFire High Level アーキテクチャ Java Client C# Client C++ Client クライアントは Cache を組 み込み可能 (with disk overflow) 物理的なサーバー群がひとつの 巨大な論理システムとしてみえ る (DistributedSystem) オブジェクトの変更がサブス クライバに伝達される 同期 R/W、非同期 Write データのパーティショニン グ・レプリケーションはクライ アントからは透過的に扱わ れる。 また、ストレージにメモリデ ータをバックアップ可能 動的にノードを追加可能
  • 37. 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
  • 38. 3838 • クライアントが distributed system に接続する方法としてGemFire server に(直接)、 または “locator” 経由で接続する方法がある • クライアントは独自にサーバーからのデータをローカルにコピー(キャッシュ)すること が可能 • クライアントはサーバー側の変更に対し register 可能。その場合変更があった際にク ライアントに通知されるようになる Client Cache Application Application Region Region Region Cache Client Cache
  • 39. 3939 • GemFire distributed system に接続、および Cache を生成するプロセス • Locator • Cacheserver (Cache 保持) • Agent • 最小構成の GemFire プロセスは組み込みモードで実行される単一のノード メンバー構成 Application Region Region Region Cache Application Region Region Region Cache Application Region Region Region Cache Application ApplicationApplication
  • 43. 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 Java Cache cache = new CacheFactory() .set("cache-xml-file", "xml/cache.xml") .create(); Region<Integer, Customer> customers = cache.getRegion("Customer");
  • 44. 4444 Creating a Cache - API Application Region Cache // Create the cache without using a cache xml file Cache cache = new CacheFactory().create(); // Create a region dynamically using the APIs Region<Integer, Customer> customers = (Region<Integer, Customer>)cache.createRegionFactory() .create("Customer”); § Classes in com.gemstone.gemfire.cache § Call cache.close() when done
  • 45. 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 を指定も可能
  • 46. 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 サポート
  • 47. 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) を利用可能
  • 48. 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) { … } }
  • 49. 4949 Spring Data Gemfire - Repositories interface PersonRepository extends CrudRepository<Person, BigInteger> { // Finder for a single entity Person findByEmailAddress(String emailAddress); // Finder for multiple entities List<Person> findByLastnameLike(String lastname); // Finder with manually defined query @Query("SELECT p FROM /Person p WHERE p.firstname = $1") List<Person> findByFirstname(String firstname); }
  • 50. 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 entity Person findByEmailAddress(String emailAddress); // Finder for multiple entities List<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); }