SlideShare a Scribd company logo
1 of 50
App Engine의 Datastore devtainer@gmail.com @devtainer
GAE/J Scalability Google Data Store
Google Data Store GoogleApp Engine이 사용하는 분산 데이터베이스 시스템 Google File System을 기반 PetaByte 급 구조화된 데이터 저장 가능 구조화된 데이터를 위한 분산 저장 시스템 범용성, 확장성, 고성능, 고가용성을 위해 개발됨 Non-Relational Database Key-Value Store JDO/JPA & Native API 지원 단위 테스트를 위한 Local 버전 App Application Django WAS Python JAVA BigTable(분산스토리지) GFS(Google File System) 리눅스OS 서버 (최소 100만대)
Bigtable의 주요 특징 Big HASHMAP NoSQL, Key/Value Store No schema Entity Group 기반 Write 비용 : Expensive Read 비용: Cheap
Google Data Store의데이터 모델 Google Data Store의 특징 Distributed Persistent Multidimensional Sorted  디자인 핵심 키워드 Fault-tolerant Persistent Scalable Self-managing 동적인 서버 확장 및 조정 MAP
Google Datastore의 장점 Excellent read performance. Excellent query performance. Transparent redundant storage and load balancing. Flexible data structure. Query indexes.
Datastore의 제약사항 Write가 느림 검색 가능한 Text 사이즈: 500 자 Entity 최대 사이즈: 1Mb 최대 Batch (save/delete) : 500 Entity SQL을 사용할 수 없음 데이터베이스의 제약조건을 적용할 수 없음 Aggregation 함수를 지원하지 않음 (count, avg) 쿼리가 최대 조회 레코드: 1000 쿼리에서 Equal 연산 이외의 조건은 1개만 추가 가능 트랜잭션의 단위는 Entity Group에 한정 됨
GAE/J Data Storage Option
Datastore Architecture Google Application Low-Level API JDO JPA Bigtable (Master Server) Tablet Tablet Tablet Tablet …………… Google File System FS 0 FS 1 FS 2 FS 3 FS 4 FS n ……
Admin Console : Datastore Statistics
Admin Console
Admin Console : Datastore Viewer
Admin Console : Datastore Indexes
Datastore Interface (Native vs Standard) Low Level API & ORM Standard (JDO & JPA) Low Level API& ORM Standard의 기능적인 차이점은 없음 Schemaless의 특정을 고려할 때 Native API가 더 적합 ORM Standard는 Google App Engine에 애플리케이션 종속성을 추상화 Datanucleus의 API 종속성을 제거 Native API를 사용할 경우 Entity 클래스를 이용하여 데이터 처리 데이터를 클래스에 맵핑하기 어려움
Native Datastore Interface
Datastore 구성 모든 Entity는 Kind가 지정 Entity는 하나이상의 Property를 포함 특정 Kind에포함된 Entity는 동일한 Property를 갖지 않음 Entity의 Property는 이름은 동일하지만 데이터 유형이 다를수 있음 Schemaless의 특성 ID는 지정하지 않을 경우 자동 할당 됨
Entity App Engine Datastore에서 관리하는 객체는 Entity Entity는 하나의 Key를 포함 모든 Entity 중 유일한 구분자 Key 의 구성 패스 Parent Entity의  key Entity의 Kind Entity에 할당된 이름 App이 할당한 값 Datastore가 지정한 numeric ID 지원 데이터 타임: integers, floating point values, strings, dates, binary data 등,  각 엔티티는 하나이상의 Property를 포함 하나의 Property에 복수의 데이터 타입 저장 가능 하나의 Property에는 복수의 값이 저장 가능 복수의 값들의 데이터 유형은 다를 수 있음
Datastore 저장 모델 주요 구성 Kind : Table Key : Primary Key Entity Group : Partitioning Property : column
Low Level API com.google.appengine.api.datastore.DatastoreService;  com.google.appengine.api.datastore.DatastoreServiceFactory; com.google.appengine.api.datastore.Entity;  com.google.appengine.api.datastore.Key; com.google.appengine.api.datastore.KeyFactory;
Entity 클래스 주요 메서드 com.google.appengine.api.datastore.Entity 생성자 public Entity(Key key)  public Entity(String kind)  public Entity(String kind, Key parent)  public Entity(String kind, String keyName)  public Entity(String kind, String keyName, Key parent)  주요 Property 관련 메서드 public Map<String,Object> getProperties()  public Object getProperty(String propertyName)  public void removeProperty(String propertyName)  public void setPropertiesFrom(Entity src)  public  void setProperty(String propertyName, Object value)
Entity 생성 DatastoreServicedatastore =  DatastoreServiceFactory.getDatastoreService(); Entity player = new Entity("Player"); player.setProperty("name", "kimyuna"); player.setProperty("age", 20); datastore.put(player); Entity player2 = new Entity("Player"); player2.setProperty("name", "Park Taehwan"); player2.setProperty("age", 21); datastore.put(player2);
Entity 생성 -schema-free DatastoreServicedatastore =  DatastoreServiceFactory.getDatastoreService(); Entity player = new Entity("Player"); player.setProperty("name", ”kimchanho"); player.setProperty(”position", “pitcher”); datastore.put(player);
Entity – Root Entity, Entity Group, Ancestor Path   Entity employee1 = new Entity("Employee"); employee1.setProperty("position", "Boss"); employee1.setProperty("age", 60); datastore.put(employee1); Entity employee2 = new Entity("Employee", employee1.getKey()); employee2.setProperty("position", "manager"); employee2.setProperty("age", 40); datastore.put(employee2); Entity employee3 = new Entity("Employee", employee2.getKey()); employee3.setProperty("position", "sub-manager"); employee3.setProperty("age", 35); datastore.put(employee3)
Entity – Root Entity, Entity Group, Ancestor Path  aglub19hcHBfaWRyDgsSCEVtcGxveWVlGAQM aglub19hcHBfaWRyHAsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQw aglub19hcHBfaWRyKgsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQwLEghFbXBsb3llZRgGDA Boss Entity Manager Entity Sub-manager Entity
aglub19hcHBfaWRyDgsSCEVtcGxveWVlGAQM Entity – Root Entity, Entity Group, Ancestor Path  Root Key  Instance Employee("BOSS") aglub19hcHBfaWRyHAsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQw Employee("BOSS")/Employee("manager") Child Key  Instance Employee("BOSS")/Employee("manager")/Employee("sub-manager") aglub19hcHBfaWRyKgsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQwLEghFbXBsb3llZRgGDA Child Key  Instance
Entity – Root Entity, Entity Group, Ancestor Path  Key.getParent() Root Key  Instance Root Entity Key.getParent() Child Key  Instance Entity  Group Ancestor Path Child Key  Instance
Root & Parent Entity & Key Root Entity Parent Entity employee Entity emp1= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8261 Entity emp1= new Entity("Employee"); datastore.put(employee); Entity address = new Entity("Address", employee.getKey()); datastore.put(address); employee, address Group Entity Employee:8261 Employee:8261 / Address:1 employee Entity emp2= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8262
Entity Group & Transaction Transaction의 최대 범위는 Entity Group Entity Group은 동일한 Tablet 서버에 위치 employee Entity emp1= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8261 Entity emp1= new Entity("Employee"); datastore.put(employee); Entity address = new Entity("Address", employee.getKey()); datastore.put(address); employee, address Group Entity Employee:8261 Employee:8261 / Address:1 employee Entity emp2= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8262
Entity Group 하나의 트랜잭션에서 여러 Entity를 조회, 생성, 수정, 삭제 할 수 가능하지만 그 범위는 단일 Entity Group에 국한 Entity Group는 부모 엔티티를 갖는 엔티티의 그룹 부모 엔티티를 가지 않은 엔티티를Root 엔티티 라고 함 Entity Group은 하나의 Root Entity와 Child Entity로 구성 하나의 엔티티 그룹은 동일한 분산 네트웍 서버에 저장됨 (Tablet 서버)
Transaction DatastoreServicedatastore =     DatastoreServiceFactory.getDatastoreService() ; Transaction txn = datastore.beginTransaction(); try {     Key employeeKey = KeyFactory.createKey("Employee", "Joe");     Entity employee = datastore.get(employeeKey);     employee.setProperty("vacationDays", 10);      datastore.put(employee);      txn.commit(); } finally {     if (txn.isActive()) {        txn.rollback();     } }
Batch Operation import java.util.Arrays;  import java.util.List;   // 코드 생략 Entity employee1 = new Entity("Employee");  Entity employee2 = new Entity("Employee");  Entity employee3 = new Entity("Employee");  //코드 생략 List<Entity> employees = Arrays.asList                      (employee1, employee2, employee3);  datastore.put(employees);
Entity & Key Class com.google.appengine.api.datastore.Entity public Entity(Key key)  public Entity(java.lang.String kind)  public Entity(java.lang.String kind, Key parent)  public Entity(java.lang.String kind, java.lang.StringkeyName)  public Entity(java.lang.String kind, java.lang.StringkeyName, Key parent)  com.google.appengine.api.datastore.KeyFactory public static Key createKey(Key parent, java.lang.String kind, long id) public static Key createKey(Key parent, java.lang.String kind,      java.lang.String name)  public static Key createKey(java.lang.String kind, long id)  public static Key createKey(java.lang.String kind, java.lang.String name)
Entity 조회, 수정, 삭제 DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Entity employee = datastore.get(rootKey); Retrieve DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Entity employee = datastore.get(rootKey); employee.setProperty(“age”, 50); datasource.put(employee); Modify DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Datastore.delete(rootKey); Remove
Query import com.google.appengine.api.datastore.DatastoreService;  import com.google.appengine.api.datastore.DatastoreServiceFactory;  import com.google.appengine.api.datastore.Entity;  import com.google.appengine.api.datastore.PreparedQuery;  import com.google.appengine.api.datastore.Query;   DatastoreServicedatastore =  DatastoreServiceFactory.getDatastoreService();   Query q = new Query(”employee")  q.addFilter("lastName", Query.FilterOperator.EQUAL, lastNameParam);  q.addFilter("height", Query.FilterOperator.LESS_THAN, maxHeightParam);   PreparedQuerypq = datastore.prepare(q);   for (Entity result : pq.asIterable()) {        String firstName = (String) result.getProperty("firstName");        String lastName = (String) result.getProperty("lastName");        Long height = (Long) result.getProperty("height");    System.out.println(lastName + " " + firstName + ", " + height.toString() + " inches tall");  }
Filter Operator Query.FilterOperator.LESS_THAN Query.FilterOperator.LESS_THAN_OR_EQUAL Query.FilterOperator.EQUAL Query.FilterOperator.GREATER_THAN Query.FilterOperator.GREATER_THAN_OR_EQUAL Query.FilterOperator.NOT_EQUAL Query.FilterOperator.IN
Java Data Object
Portability 확보
JPA와 JDO어노테이션으로ORM 설정 가능 두 표준간의 기능적인 차이는 없음 JDO-QL과 JPA-QL 사용 가능 JPA 2.0  (Data Nucleus JDO 구현체를 Provider로 사용) JDO 2.3 Data Nucleus 의 JDO Provider Low Level API Datastore Interface (JDO vs JPA) Google Datastore
Datastore Interface (JDO & JPA) JPA(Java Persistence API) RDBMS를 저장소로 테이블과 객체 맵핑 표준 스펙 JDO(Java Data Object) Non-RDBMS를 포함하는 저장소를 대상으로 하는 객체 맵핑 표준
App Engine의 JDO App Engine Java SDK는 JDO 구현체를 포함 Datastore의 영속성 인터페이스로 지원 Version: JDO 2.3 DataNucleus Access Platform의 구현체 사용
JDO 설치-jdoconfig.xml & JAR war/WEB-INF/classes/META-INF/jdoconfig.xml 라이브러리 추가 war/WEB-INF/lib/appengine-api.jar
JDO 설치-Enhance 프로세스 적용 클래스 컴파일 후 POJO Enhance 프로세스 적용 java -cpclasspathcom.google.appengine.tools.enhancer.Enhanceclass-files appengine-java-sdk/lib/appengine-tools-api.jar
JDO 설치-Enhance 프로세스 적용 in Eclipse
JDO 설치-Enhance 프로세스 적용 in maven
JDO 설치-Enhance 프로세스 적용 in Ant <property name="sdk.dir" location="../appengine-java-sdk" /> <import file="${sdk.dir}/config/user/ant-macros.xml" />  <target name="datanucleusenhance" depends="compile"       description="Performs JDO enhancement on compiled data classes.">     <enhance_war war="war" /> </target> <target name="runserver" depends="datanucleusenhance"       description="Starts the development server.">     <dev_appserver war="war" port="8888" >       <options>         <argvalue="--jvm_flag=-Xdebug"/>         <argvalue="--jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999"/>       </options>     </dev_appserver> </target>
JDO 설치-PMF 클래스 import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; public final class PMF { private static final PersistenceManagerFactorypmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); private PMF() {} public static PersistenceManagerFactory get() { return pmfInstance; } } //PersistenceManagerpm = PMF.get().getPersistenceManager();
데이터 클래스 import com.google.appengine.api.datastore.Key; import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; @PersistenceCapable public class Employee {     @PrimaryKey     @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)     private Key key;     @Persistentprivate String firstName;     @Persistentprivate String lastName;     @Persistentprivate Date hireDate; // 생성자 getter setter 생략 }
Object 영속성 PersistenceManager pm = PMF.get().getPersistenceManager(); Employee e = new Employee(”Park", ”Chanho", new Date()); try {       pm.makePersistent(e); } finally {       pm.close(); }
Object 영속성-II public void updateEmployeeTitle(User user, String newTitle) {     PersistenceManager pm = PMF.get().getPersistenceManager();     try {         Employee e = pm.getObjectById(Employee.class, user.getEmail());         if (titleChangeIsAuthorized(e, newTitle) {             e.setTitle(newTitle);         } else {             throw new UnauthorizedTitleChangeException(e, newTitle);         }     } finally {         pm.close();     } } pm.deletePersistent(e);
Q&A

More Related Content

Similar to N03 app engineseminar

Mini charla jquery
Mini charla jqueryMini charla jquery
Mini charla jquerylizardoceliz
 
Fatih BAZMAN CodeIgniter Sunumu
Fatih BAZMAN CodeIgniter SunumuFatih BAZMAN CodeIgniter Sunumu
Fatih BAZMAN CodeIgniter SunumuFatih Bazman
 
Core rest edgarsilva_v1
Core rest edgarsilva_v1Core rest edgarsilva_v1
Core rest edgarsilva_v1Edgar Silva
 
Boostのあるプログラミング生活
Boostのあるプログラミング生活Boostのあるプログラミング生活
Boostのあるプログラミング生活Akira Takahashi
 
03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...Warawut
 
Chico-UI en escuela DaVinci
Chico-UI en escuela DaVinciChico-UI en escuela DaVinci
Chico-UI en escuela DaVinciNatan Santolo
 
ADO.NET Entity Framework 4
ADO.NET Entity Framework 4ADO.NET Entity Framework 4
ADO.NET Entity Framework 4Raffaele Fanizzi
 
No sql pour valtech tech days
No sql pour valtech tech daysNo sql pour valtech tech days
No sql pour valtech tech daysClaude Falguiere
 
Entity+framework+
Entity+framework+Entity+framework+
Entity+framework+Rey zhang
 
Modelos de Datos, Clasificación, Propósitos y Componentes
Modelos de Datos, Clasificación, Propósitos y ComponentesModelos de Datos, Clasificación, Propósitos y Componentes
Modelos de Datos, Clasificación, Propósitos y ComponentesJuan Sebastián Ordoñez Monroy
 
MongoDB Indexing: The Details
MongoDB Indexing: The DetailsMongoDB Indexing: The Details
MongoDB Indexing: The DetailsMongoDB
 
Вебинар Томулевича materialized.path 2
Вебинар Томулевича materialized.path 2 Вебинар Томулевича materialized.path 2
Вебинар Томулевича materialized.path 2 Media Gorod
 
Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...PyData
 
Lecture6
Lecture6Lecture6
Lecture6orgil
 

Similar to N03 app engineseminar (17)

MS Swit 2010
MS Swit 2010MS Swit 2010
MS Swit 2010
 
Mini charla jquery
Mini charla jqueryMini charla jquery
Mini charla jquery
 
Fatih BAZMAN CodeIgniter Sunumu
Fatih BAZMAN CodeIgniter SunumuFatih BAZMAN CodeIgniter Sunumu
Fatih BAZMAN CodeIgniter Sunumu
 
Türsteher für Bohnen
Türsteher für BohnenTürsteher für Bohnen
Türsteher für Bohnen
 
Core rest edgarsilva_v1
Core rest edgarsilva_v1Core rest edgarsilva_v1
Core rest edgarsilva_v1
 
Boostのあるプログラミング生活
Boostのあるプログラミング生活Boostのあるプログラミング生活
Boostのあるプログラミング生活
 
03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...
 
Der lachende Dritte
Der lachende DritteDer lachende Dritte
Der lachende Dritte
 
Chico-UI en escuela DaVinci
Chico-UI en escuela DaVinciChico-UI en escuela DaVinci
Chico-UI en escuela DaVinci
 
ADO.NET Entity Framework 4
ADO.NET Entity Framework 4ADO.NET Entity Framework 4
ADO.NET Entity Framework 4
 
No sql pour valtech tech days
No sql pour valtech tech daysNo sql pour valtech tech days
No sql pour valtech tech days
 
Entity+framework+
Entity+framework+Entity+framework+
Entity+framework+
 
Modelos de Datos, Clasificación, Propósitos y Componentes
Modelos de Datos, Clasificación, Propósitos y ComponentesModelos de Datos, Clasificación, Propósitos y Componentes
Modelos de Datos, Clasificación, Propósitos y Componentes
 
MongoDB Indexing: The Details
MongoDB Indexing: The DetailsMongoDB Indexing: The Details
MongoDB Indexing: The Details
 
Вебинар Томулевича materialized.path 2
Вебинар Томулевича materialized.path 2 Вебинар Томулевича materialized.path 2
Вебинар Томулевича materialized.path 2
 
Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...Python and pandas as back end to real-time data driven applications by Giovan...
Python and pandas as back end to real-time data driven applications by Giovan...
 
Lecture6
Lecture6Lecture6
Lecture6
 

N03 app engineseminar

  • 1. App Engine의 Datastore devtainer@gmail.com @devtainer
  • 3. Google Data Store GoogleApp Engine이 사용하는 분산 데이터베이스 시스템 Google File System을 기반 PetaByte 급 구조화된 데이터 저장 가능 구조화된 데이터를 위한 분산 저장 시스템 범용성, 확장성, 고성능, 고가용성을 위해 개발됨 Non-Relational Database Key-Value Store JDO/JPA & Native API 지원 단위 테스트를 위한 Local 버전 App Application Django WAS Python JAVA BigTable(분산스토리지) GFS(Google File System) 리눅스OS 서버 (최소 100만대)
  • 4. Bigtable의 주요 특징 Big HASHMAP NoSQL, Key/Value Store No schema Entity Group 기반 Write 비용 : Expensive Read 비용: Cheap
  • 5. Google Data Store의데이터 모델 Google Data Store의 특징 Distributed Persistent Multidimensional Sorted 디자인 핵심 키워드 Fault-tolerant Persistent Scalable Self-managing 동적인 서버 확장 및 조정 MAP
  • 6. Google Datastore의 장점 Excellent read performance. Excellent query performance. Transparent redundant storage and load balancing. Flexible data structure. Query indexes.
  • 7. Datastore의 제약사항 Write가 느림 검색 가능한 Text 사이즈: 500 자 Entity 최대 사이즈: 1Mb 최대 Batch (save/delete) : 500 Entity SQL을 사용할 수 없음 데이터베이스의 제약조건을 적용할 수 없음 Aggregation 함수를 지원하지 않음 (count, avg) 쿼리가 최대 조회 레코드: 1000 쿼리에서 Equal 연산 이외의 조건은 1개만 추가 가능 트랜잭션의 단위는 Entity Group에 한정 됨
  • 9. Datastore Architecture Google Application Low-Level API JDO JPA Bigtable (Master Server) Tablet Tablet Tablet Tablet …………… Google File System FS 0 FS 1 FS 2 FS 3 FS 4 FS n ……
  • 10. Admin Console : Datastore Statistics
  • 12. Admin Console : Datastore Viewer
  • 13. Admin Console : Datastore Indexes
  • 14. Datastore Interface (Native vs Standard) Low Level API & ORM Standard (JDO & JPA) Low Level API& ORM Standard의 기능적인 차이점은 없음 Schemaless의 특정을 고려할 때 Native API가 더 적합 ORM Standard는 Google App Engine에 애플리케이션 종속성을 추상화 Datanucleus의 API 종속성을 제거 Native API를 사용할 경우 Entity 클래스를 이용하여 데이터 처리 데이터를 클래스에 맵핑하기 어려움
  • 16. Datastore 구성 모든 Entity는 Kind가 지정 Entity는 하나이상의 Property를 포함 특정 Kind에포함된 Entity는 동일한 Property를 갖지 않음 Entity의 Property는 이름은 동일하지만 데이터 유형이 다를수 있음 Schemaless의 특성 ID는 지정하지 않을 경우 자동 할당 됨
  • 17. Entity App Engine Datastore에서 관리하는 객체는 Entity Entity는 하나의 Key를 포함 모든 Entity 중 유일한 구분자 Key 의 구성 패스 Parent Entity의 key Entity의 Kind Entity에 할당된 이름 App이 할당한 값 Datastore가 지정한 numeric ID 지원 데이터 타임: integers, floating point values, strings, dates, binary data 등, 각 엔티티는 하나이상의 Property를 포함 하나의 Property에 복수의 데이터 타입 저장 가능 하나의 Property에는 복수의 값이 저장 가능 복수의 값들의 데이터 유형은 다를 수 있음
  • 18. Datastore 저장 모델 주요 구성 Kind : Table Key : Primary Key Entity Group : Partitioning Property : column
  • 19. Low Level API com.google.appengine.api.datastore.DatastoreService; com.google.appengine.api.datastore.DatastoreServiceFactory; com.google.appengine.api.datastore.Entity; com.google.appengine.api.datastore.Key; com.google.appengine.api.datastore.KeyFactory;
  • 20. Entity 클래스 주요 메서드 com.google.appengine.api.datastore.Entity 생성자 public Entity(Key key) public Entity(String kind) public Entity(String kind, Key parent) public Entity(String kind, String keyName) public Entity(String kind, String keyName, Key parent) 주요 Property 관련 메서드 public Map<String,Object> getProperties() public Object getProperty(String propertyName) public void removeProperty(String propertyName) public void setPropertiesFrom(Entity src) public void setProperty(String propertyName, Object value)
  • 21. Entity 생성 DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Entity player = new Entity("Player"); player.setProperty("name", "kimyuna"); player.setProperty("age", 20); datastore.put(player); Entity player2 = new Entity("Player"); player2.setProperty("name", "Park Taehwan"); player2.setProperty("age", 21); datastore.put(player2);
  • 22. Entity 생성 -schema-free DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Entity player = new Entity("Player"); player.setProperty("name", ”kimchanho"); player.setProperty(”position", “pitcher”); datastore.put(player);
  • 23. Entity – Root Entity, Entity Group, Ancestor Path Entity employee1 = new Entity("Employee"); employee1.setProperty("position", "Boss"); employee1.setProperty("age", 60); datastore.put(employee1); Entity employee2 = new Entity("Employee", employee1.getKey()); employee2.setProperty("position", "manager"); employee2.setProperty("age", 40); datastore.put(employee2); Entity employee3 = new Entity("Employee", employee2.getKey()); employee3.setProperty("position", "sub-manager"); employee3.setProperty("age", 35); datastore.put(employee3)
  • 24. Entity – Root Entity, Entity Group, Ancestor Path aglub19hcHBfaWRyDgsSCEVtcGxveWVlGAQM aglub19hcHBfaWRyHAsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQw aglub19hcHBfaWRyKgsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQwLEghFbXBsb3llZRgGDA Boss Entity Manager Entity Sub-manager Entity
  • 25. aglub19hcHBfaWRyDgsSCEVtcGxveWVlGAQM Entity – Root Entity, Entity Group, Ancestor Path Root Key Instance Employee("BOSS") aglub19hcHBfaWRyHAsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQw Employee("BOSS")/Employee("manager") Child Key Instance Employee("BOSS")/Employee("manager")/Employee("sub-manager") aglub19hcHBfaWRyKgsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQwLEghFbXBsb3llZRgGDA Child Key Instance
  • 26. Entity – Root Entity, Entity Group, Ancestor Path Key.getParent() Root Key Instance Root Entity Key.getParent() Child Key Instance Entity Group Ancestor Path Child Key Instance
  • 27. Root & Parent Entity & Key Root Entity Parent Entity employee Entity emp1= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8261 Entity emp1= new Entity("Employee"); datastore.put(employee); Entity address = new Entity("Address", employee.getKey()); datastore.put(address); employee, address Group Entity Employee:8261 Employee:8261 / Address:1 employee Entity emp2= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8262
  • 28. Entity Group & Transaction Transaction의 최대 범위는 Entity Group Entity Group은 동일한 Tablet 서버에 위치 employee Entity emp1= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8261 Entity emp1= new Entity("Employee"); datastore.put(employee); Entity address = new Entity("Address", employee.getKey()); datastore.put(address); employee, address Group Entity Employee:8261 Employee:8261 / Address:1 employee Entity emp2= new Entity("Employee"); datastore.put(employee); Group Entity Employee:8262
  • 29. Entity Group 하나의 트랜잭션에서 여러 Entity를 조회, 생성, 수정, 삭제 할 수 가능하지만 그 범위는 단일 Entity Group에 국한 Entity Group는 부모 엔티티를 갖는 엔티티의 그룹 부모 엔티티를 가지 않은 엔티티를Root 엔티티 라고 함 Entity Group은 하나의 Root Entity와 Child Entity로 구성 하나의 엔티티 그룹은 동일한 분산 네트웍 서버에 저장됨 (Tablet 서버)
  • 30. Transaction DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService() ; Transaction txn = datastore.beginTransaction(); try {     Key employeeKey = KeyFactory.createKey("Employee", "Joe");     Entity employee = datastore.get(employeeKey);     employee.setProperty("vacationDays", 10);      datastore.put(employee);      txn.commit(); } finally {     if (txn.isActive()) {        txn.rollback();     } }
  • 31. Batch Operation import java.util.Arrays; import java.util.List; // 코드 생략 Entity employee1 = new Entity("Employee"); Entity employee2 = new Entity("Employee"); Entity employee3 = new Entity("Employee"); //코드 생략 List<Entity> employees = Arrays.asList (employee1, employee2, employee3); datastore.put(employees);
  • 32. Entity & Key Class com.google.appengine.api.datastore.Entity public Entity(Key key) public Entity(java.lang.String kind) public Entity(java.lang.String kind, Key parent) public Entity(java.lang.String kind, java.lang.StringkeyName) public Entity(java.lang.String kind, java.lang.StringkeyName, Key parent) com.google.appengine.api.datastore.KeyFactory public static Key createKey(Key parent, java.lang.String kind, long id) public static Key createKey(Key parent, java.lang.String kind, java.lang.String name) public static Key createKey(java.lang.String kind, long id) public static Key createKey(java.lang.String kind, java.lang.String name)
  • 33. Entity 조회, 수정, 삭제 DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Entity employee = datastore.get(rootKey); Retrieve DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Entity employee = datastore.get(rootKey); employee.setProperty(“age”, 50); datasource.put(employee); Modify DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Key rootKey = KeyFactory.createKey("Employee", "BOSS"); Datastore.delete(rootKey); Remove
  • 34. Query import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.PreparedQuery; import com.google.appengine.api.datastore.Query; DatastoreServicedatastore = DatastoreServiceFactory.getDatastoreService(); Query q = new Query(”employee") q.addFilter("lastName", Query.FilterOperator.EQUAL, lastNameParam); q.addFilter("height", Query.FilterOperator.LESS_THAN, maxHeightParam); PreparedQuerypq = datastore.prepare(q); for (Entity result : pq.asIterable()) { String firstName = (String) result.getProperty("firstName"); String lastName = (String) result.getProperty("lastName"); Long height = (Long) result.getProperty("height"); System.out.println(lastName + " " + firstName + ", " + height.toString() + " inches tall"); }
  • 35. Filter Operator Query.FilterOperator.LESS_THAN Query.FilterOperator.LESS_THAN_OR_EQUAL Query.FilterOperator.EQUAL Query.FilterOperator.GREATER_THAN Query.FilterOperator.GREATER_THAN_OR_EQUAL Query.FilterOperator.NOT_EQUAL Query.FilterOperator.IN
  • 38. JPA와 JDO어노테이션으로ORM 설정 가능 두 표준간의 기능적인 차이는 없음 JDO-QL과 JPA-QL 사용 가능 JPA 2.0 (Data Nucleus JDO 구현체를 Provider로 사용) JDO 2.3 Data Nucleus 의 JDO Provider Low Level API Datastore Interface (JDO vs JPA) Google Datastore
  • 39. Datastore Interface (JDO & JPA) JPA(Java Persistence API) RDBMS를 저장소로 테이블과 객체 맵핑 표준 스펙 JDO(Java Data Object) Non-RDBMS를 포함하는 저장소를 대상으로 하는 객체 맵핑 표준
  • 40. App Engine의 JDO App Engine Java SDK는 JDO 구현체를 포함 Datastore의 영속성 인터페이스로 지원 Version: JDO 2.3 DataNucleus Access Platform의 구현체 사용
  • 41. JDO 설치-jdoconfig.xml & JAR war/WEB-INF/classes/META-INF/jdoconfig.xml 라이브러리 추가 war/WEB-INF/lib/appengine-api.jar
  • 42. JDO 설치-Enhance 프로세스 적용 클래스 컴파일 후 POJO Enhance 프로세스 적용 java -cpclasspathcom.google.appengine.tools.enhancer.Enhanceclass-files appengine-java-sdk/lib/appengine-tools-api.jar
  • 43. JDO 설치-Enhance 프로세스 적용 in Eclipse
  • 45. JDO 설치-Enhance 프로세스 적용 in Ant <property name="sdk.dir" location="../appengine-java-sdk" /> <import file="${sdk.dir}/config/user/ant-macros.xml" />  <target name="datanucleusenhance" depends="compile"       description="Performs JDO enhancement on compiled data classes.">     <enhance_war war="war" /> </target> <target name="runserver" depends="datanucleusenhance"       description="Starts the development server.">     <dev_appserver war="war" port="8888" >       <options>         <argvalue="--jvm_flag=-Xdebug"/>         <argvalue="--jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999"/>       </options>     </dev_appserver> </target>
  • 46. JDO 설치-PMF 클래스 import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory; public final class PMF { private static final PersistenceManagerFactorypmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); private PMF() {} public static PersistenceManagerFactory get() { return pmfInstance; } } //PersistenceManagerpm = PMF.get().getPersistenceManager();
  • 47. 데이터 클래스 import com.google.appengine.api.datastore.Key; import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; @PersistenceCapable public class Employee {     @PrimaryKey     @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)     private Key key;     @Persistentprivate String firstName;     @Persistentprivate String lastName;     @Persistentprivate Date hireDate; // 생성자 getter setter 생략 }
  • 48. Object 영속성 PersistenceManager pm = PMF.get().getPersistenceManager(); Employee e = new Employee(”Park", ”Chanho", new Date()); try {       pm.makePersistent(e); } finally {       pm.close(); }
  • 49. Object 영속성-II public void updateEmployeeTitle(User user, String newTitle) {     PersistenceManager pm = PMF.get().getPersistenceManager();     try {         Employee e = pm.getObjectById(Employee.class, user.getEmail());         if (titleChangeIsAuthorized(e, newTitle) {             e.setTitle(newTitle);         } else {             throw new UnauthorizedTitleChangeException(e, newTitle);         }     } finally {         pm.close();     } } pm.deletePersistent(e);
  • 50. Q&A