Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Spring Data in a Nutshell

3.343 visualizaciones

Publicado el

Publicado en: Tecnología
  • Sé el primero en comentar

Spring Data in a Nutshell

  1. 1. © 2012 SpringSource, A division of VMware. All rights reserved Spring Data in a Nutshell Tsuyoshi Miyake (@tsuyokb)
  2. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 20. 2020 Spring Data Mongo - Repositories § Spring Data Commons の Repository 同様 • インタフェースの定義(のみ) & naming convention
  21. 21. 2121 Spring Data Mongo – Repository 使用法 or @EnableMongoRepositories in JavaConfig
  22. 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/ で
  23. 23. 2323 Neo4j データモデル
  24. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 35. 3535 • 分散/メモリーベースのデータ管理プラットフォ ーム • データトランザクションの多いアプリケーション に対し、可用性、高パフォーマンス、スケーラビ リティを提供 • データの一貫性を場合に応じて調節可能(分散 ロックのレベル) • イベントドリブンなアーキテクチャ … 続きは http://www.vmware.com/support/pubs/vfabri c-gemfire.html で GemFire – The Enterprise Data Fabric Java Client C# Client C++ Client
  36. 36. 3636 GemFire High Level アーキテクチャ Java Client C# Client C++ Client クライアントは Cache を組 み込み可能 (with disk overflow) 物理的なサーバー群がひとつの 巨大な論理システムとしてみえ る (DistributedSystem) オブジェクトの変更がサブス クライバに伝達される 同期 R/W、非同期 Write データのパーティショニン グ・レプリケーションはクライ アントからは透過的に扱わ れる。 また、ストレージにメモリデ ータをバックアップ可能 動的にノードを追加可能
  37. 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. 38. 3838 • クライアントが distributed system に接続する方法としてGemFire server に(直接)、 または “locator” 経由で接続する方法がある • クライアントは独自にサーバーからのデータをローカルにコピー(キャッシュ)すること が可能 • クライアントはサーバー側の変更に対し register 可能。その場合変更があった際にク ライアントに通知されるようになる Client Cache Application Application Region Region Region Cache Client Cache
  39. 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
  40. 40. 4040 GemFire Topologies Embedded Peer-To-Peer Client/Server Multi-site/WAN Gateway Topologies of GemFire
  41. 41. 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
  42. 42. 4242 Topologies – Client-Server ApplicationApplicationApplication Application Region Region Region Cache Application Region Region Region Cache Application Region Region Region Cache
  43. 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. 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. 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. 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. 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. 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. 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. 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); }
  51. 51. 5151 Thank you! Q&A @tsuyokb

×