M.C. Kang
   Overview
                                                                Spring Data is a high level
                                                               SpringSource project whose purpose is to
                                                               unify and ease the access to different
                                                               kinds of persistence stores, both
                                                               relational database systems and NoSQL
                                                               data stores.




      Source http://www.infoq.com/articles/spring-data-intro




Spring Data projects support the followings aspects:
Templating
Object/Datastore mapping
Repository support
   Overview - Templates
  The main purpose of a Spring Data template (and all other Spring templates) is resource
  allocation and exception translation.


  A template offers store specific operations like saving, updating and deleting a single
  record or for executing queries or map/reduce jobs. But all these methods work only for the
  corresponding underlying datastore.




MongoDb Template Configuration Example
<!-- Connection to MongoDB server -->
<mongo:db-factory host="localhost" port="27017" dbname="test" />
<!-- MongoDB Template -->
<bean id="mongoTemplate“
class="org.springframework.data.mongodb.core.MongoTemplate">
          <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
     Overview - Object/Datastore Mapping
    With Spring Data, this support is extended to NoSQL datastores with object-like data structures. But
    these data structures can be quite different from each other, so it would be difficult to
    make up a common API for object/datastore mapping. Each type of datastore comes with its own set of
    annotations to provide the needed meta information for the mapping.




                       JPA                                                MongoDB                                           Neo4j
@Entity                                                  @Document( collection="usr")                      @NodeEntity
@Table(name="TUSR")                                      public class User {                               public class User {   
public class User {                                               @Id   private String id;                         @GraphId   Long id;  
          @Id    private String id;                               @Field("fn")   private String name;               private String name;   
          @Column(name="fn")   private String name;               private Date lastLogin;                          private Date lastLogin;
          private Date lastLogin;                                   ...                                            ...
          ...                                             }                                                }
}
   Overview - Repository Support
generic support for CRUD and paging , sorting by providing special parameters to the finder
methods for all persistence stores


The main advantages of repository support are:
     The developer writes a lot less boilerplate code
     Queries can by defined alongside the finder method and its documentation
     As a bonus, the JPQL queries are compiled as soon as the Spring context is assembled,
     not the first time you use the query, which makes it easier to detect syntax errors
    Data Model                                 Domain Model

    Customer                       Address


                                                        <<MappedSuperClass>>
                                                              AbstractEntity

CREATE TABLE customer (
 id BIGINT IDENTITY PRIMARY KEY,
 firstname VARCHAR(255),
 lastname VARCHAR(255),
 email_address VARCHAR(255));
                                                               <<Entity>>
CREATE UNIQUE INDEX ix_customer_email                           Customer
ON CUSTOMER (email_address ASC);

CREATE TABLE address (
 id BIGINT IDENTITY PRIMARY KEY,
 customer_id BIGINT CONSTRAINT
address_customer_ref REFERENCES
customer (id),
 street VARCHAR(255),
 city VARCHAR(255),                              <<Entity>>            <<Embeddable>>
 country VARCHAR(255));
                                                  Address                  EmailAddress




                         Step1. “Define Domain Model”
    AbstractEntity                                                        Customer
@M appedSupercl ass                                                @Entity
public class AbstractEntity {                                      public class Customer extends AbstractEntity {

          @Id                                                               private String firstname, lastname;
          @GeneratedValue(strategy = GenerationT ype. AUTO)
          private Long id;                                                  @Col umn(unique = true)
                                                                            private EmailAddress emailAddress;
          public Long getId() {
                    return id;                                              @OneToMany(cascade = CascadeType.ALL, orphanRemoval =
          }                                                                 true)
                                                                            @JoinColumn(nam e = "custom er_id")
          public boolean equals(Object obj) {                               private Set<Address> addresses = new HashSet<Address>();
                    if (this == obj) {
                    return true;                                            public Customer(String firstname, String lastname) {
                    }
                                                                                      Assert.hasText(firstname);
                     if (this.id == null || obj == null || !                          Assert.hasText(lastname);
                     (this.getClass().equals(obj.getClass()))) {
                                              return false;                           this.firstname = firstname;
                     }                                                                this.lastname = lastname;
                                                                            }
                     AbstractEntity that = (AbstractEntity) obj;
                                                                            protected Customer() {
                     return this.id.equals(that.getId());
          }                                                                 }

          public int hashCode() {                                           public void add(Address address) {
                     return id == null ? 0 : id.hashCode();
          }                                                                           Assert.notNull(address);
}                                                                                     this.addresses.add(address);
                                                                            }
                                                                            …
    @MappedSuperclass to express that it is not a                      If there were demand to customize the names of the
    managed                                                            columns to which the properties would be persisted,
    entity class on its own but rather will be extended                you could use the @Column annotation.
    by entity classes.




                                                   Step1. “Define Domain Model”
   Address                                                                  CustomerRepository
@Entity                                                                          public interface CustomerRepository
public class Address extends AbstractEntity {                                                         ext ends CrudRepos itory<Customer, Long> {
                                                                                            Customer findByEmailAddress(EmailAddress emailAddress);
private String street, city, country;                                                       Customer findById(Long id);
                                                                                            List<Customer> findAll();
public Address(String street, String city, String country) {                     }

            Assert.hasText(street, "Street must not be null or empty!");
            Assert.hasText(city, "City must not be null or empty!");
            Assert.hasText(country, "Country must not be null or empty!");

            this.street = street;
            this.city = city;
            this.country = country;
                                                                                            Step2. “Define Repository
}                                                                                                   Interface”
protected Address() {
                                                                                               -Just only interface
}
    …


           EmailAddress
@Em beddabl e
public class EmailAddress {

@Colum n(nam e = "email_address")
private String value;

public EmailAddress(String emailAddress) {
         Assert.isTrue(isValid(emailAddress), "Invalid email address!");
         this.value = emailAddress;
}
                                                                             the EmailAddress class is an @Embeddable, which
protected EmailAddress() {                                                   will cause the persistence provider to flatten out
                                                                             all properties of it into the table of the
}
…                                                                            surrounding class.


        Step1. “Define Domain Model”
    SpringConfig
@Configuration
@EnableT ransactionManagement
@ComponentS can
@EnableJ paReposi tories
public class InfrastructureConfig {

@Bean
public DataSource dataSource() {
          return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:sql/schema.sql")
          .addScript("classpath:sql/test-data.sql").build();
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
          HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
          vendorAdapter.setDatabase(Database.HSQL);
          //vendorAdapter.setGenerateDdl(true);
          vendorAdapter.setShowSql(true);
          LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
          factory.setJpaVendorAdapter(vendorAdapter);
          factory.setPackagesToScan(getClass().getPackage().getName());
          factory.setDataSource(dataSource());
          return factory;
}

@Bean
public PlatformTransactionManager transactionManager() {
          JpaTransactionManager txManager = new JpaTransactionManager();
          txManager.setEntityManagerFactory(entityManagerFactory().getObject());
          return txManager;
}
}




                                        Step3. “Configure Spring Beans”
     TestCase
@RunWit h(SpringJUnit4Cl assRunner.class)                                               @Test
@Cont extConfiguration(classes = { TestConfig.cl ass })                                 public void saveNewCustomer() {
@T ransactional                                                                         Customer c = new Customer();
@Di rtiesContext                                                                        //c.setFirstname("Sven");
public class TestMain {                                                                 c.setLastname("Svensson");
                                                                                        c.setEmailAddress(new EmailAddress("sven@svensson.org"));
@A utowired                                                                             Address a = new Address("Storgaten 6", "Trosa", "Sweden");
CustomerRepository repository;                                                          c.add(a);
                                                                                        repository.save(c);
@Autowired                                                                              System.out.println(repository.findAll());
DataSource dataSource;                                                                  Customer result = repository.findOne(c.getId());
                                                                                        assertThat(result, is(notNullValue()));
@Test                                                                                   //assertThat(result.getFirstName(), is("Sven"));
public void testFindAll() {                                                             assertThat(result.getEmailAddress().toString(), is(notNullValue()));
List< Custom er> results = reposi tory.findAl l();                                      }
assertThat(results, is(notNullValue()));
assertThat(results, hasSize(3));
assertThat(results.get(0), notNullValue());                                             @Test(expected = DataIntegrityViolationException.class)
assertThat(results.get(1), notNullValue());                                             public void saveNewCustomerWithDuplicateEmail() {
assertThat(results.get(2), notNullValue());                                             Customer c = new Customer("Bob","Doe");
}                                                                                       c.setEmailAddress(new EmailAddress("bob@doe.com"));
                                                                                        Address a = new Address("66 Main St", "Middletown", "USA");
@Test                                                                                   c.add(a);
public void testFindById() {                                                            repository.save(c);
Customer res ult = repository.findOne(100L);                                            }
assertThat(result, is(notNullValue()));
assertThat(result.getFirstname(), is("John"));                                      @Test
}                                                                                   public void deleteCustomer() {
                                                                                    Customer c = repository.findOne(100L);
@Test                                                                               repository.delete(c);
public void testFindByEmail() {                                                     Customer result = repository.findOne(100L);
                                                                                    assertThat(result, is(nullValue()));
Customer result = repository.fi ndByEm ail Address(new EmailA ddress("bob@doe.com"));
assertThat(result, is(notNullValue()));                                             }
assertThat(result.getFirstname(), is("Bob"));
}                                                                                   }




                                                          Step4. “Test it…”
   Document Model                              Domain Model

                   Customer

        Email                 (*)Address
                                                              AbstractDocument


{
  firstname : "Dave",
  lastname : "Matthews",
  email : {
             email : "dave@dmband.com"
                                                               <<Document>>
            },
  addresses : [                                                  Customer
                    {
                      street : "Broadway",
                      city : "New York",
                      country : "United
States"
                    }
                  ]
}
                                                 <<Entity>>             <<Embeddable>>
                                                  Address                   EmailAddress




                           Step1. “Define Domain Model”
     AbstractDocument                                                        Customer
public class AbstractDocument {                                      @Document
                                                                     public class Customer extends AbstractDocument {
         @Id
         private BigInteger id;                                               private String firstname, lastname;

         public BigInteger getId() {                                          @Fi eld("em ail ")
                   return id;                                                 @Indexed(unique = true)
         }                                                                    private EmailAddress emailAddress;
                                                                              private Set<Address> addresses = new HashSet<Address>();
         public boolean equals(Object obj) {
                                                                              public Customer(String firstname, String lastname) {
                   if (this == obj) {
                   return true;                                               Assert.hasText(firstname);
                   }                                                          Assert.hasText(lastname);

                   if (this.id == null || obj == null || !                    this.firstname = firstname;
                   (this.getClass().equals(obj.getClass()))) {                this.lastname = lastname;
                   return false;                                              }
                   }
                                                                              protected Customer() {
                   AbstractDocument that = (AbstractDocument) obj;
                                                                              }
                   return this.id.equals(that.getId());                       …
         }

         public int hashCode() {
                    return id == null ? 0 : id.hashCode();
         }
}




                                                 Step1. “Define Domain Model”
   Address                                                                       CustomerRepository
public class Address {                                                                public interface CustomerRepository
                                                                                                           ext ends CrudRepos itory<Customer, Long> {
            private final String street, city, country;                                          Customer findByEmailAddress(EmailAddress emailAddress);
                                                                                                 Customer findById(Long id);
            public Address(String street, String city, String country) {                         List<Customer> findAll();
                                                                                      }
                       Assert.hasText(street, "Street must not be null or empty!");
                       Assert.hasText(city, "City must not be null or empty!");
                       Assert.hasText(country, "Country must not be null or
                       empty!");

                       this.street = street;
                       this.city = city;
                       this.country = country;
                                                                                                 Step2. “Define Repository
 …
            }                                                                                            Interface”
                                                                                                    -Just only interface

           EmailAddress
public class EmailAddress {

@F iel d("emai l")
private final String value;

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

protected EmailAddress() {

}
…




        Step1. “Define Domain Model”
   SpringConfig
@Configuration
@ComponentS can
@EnableM ongoRepositories(baseP ackages="com.mck ang.springdata.mongo")
class ApplicationConfig extends AbstractMongoConfiguration {

       @Autowired
       private List<Converter<?, ?>> converters;

       protected String getDatabaseName() {
                 return "e-store";
       }

       public Mongo mongo() throws Exception {

                Mongo mongo = new Mongo("127.0.0.1");
                mongo.setWriteConcern(WriteConcern.FSYNC_SAFE);

                return mongo;
       }

       public CustomConversions customConversions() {
                 return new CustomConversions(converters);
       }

       protected String get MappingBasePackage () {
                 return "com.mckang.springdata.mongo";
       }
}




                                      Step3. “Configure Spring Beans”
     TestCase
@RunWith(S pringJUnit4ClassRunner.class )                                                  @Test
@ContextConfigurati on(cl asses = { T es tConfi g.class })                                 public void saveNewCustomer() {
@T ransactional                                                                                       Customer c = new Customer();
@DirtiesContext                                                                                       //c.setFirstname("Sven");
public class TestMain {                                                                               c.setLastname("Svensson");
                                                                                                      c.setEmailAddress(new EmailAddress("sven@svensson.org"));
@Autowi red                                                                                           Address a = new Address("Storgaten 6", "Trosa", "Sweden");
Custom erRepository reposi tory;                                                                      c.add(a);
                                                                                                      repository.save(c);
@Autowired                                                                                 }
DataSource dataSource;

@Test                                                                                      @Test(expected = DataIntegrityViolationException.class)
public void testFindAll() {                                                                public void saveNewCustomerWithDuplicateEmail() {
           List<Custom er> results = repository.f indAll ();                                          Customer c = new Customer("Bob","Doe");
           assertThat(results, is(notNullValue()));                                                   c.setEmailAddress(new EmailAddress("bob@doe.com"));
           assertThat(results, hasSize(3));                                                           Address a = new Address("66 Main St", "Middletown", "USA");
           assertThat(results.get(0), notNullValue());                                                c.add(a);
           assertThat(results.get(1), notNullValue());                                                repository.save(c);
           assertThat(results.get(2), notNullValue());                                     }
}
                                                                                           @Test
@Test                                                                                      public void deleteCustomer() {
public void testFindById() {                                                                          Customer c = repository.findOne(100L);
           Custom er result = repos it ory.findOne(100L);                                             repository.delete(c);
           assertThat(result, is(notNullValue()));                                         }
           assertThat(result.getFirstname(), is("John"));
}                                                                                          }

@Test
public void testFindByEmail() {
         Customer result = repository.f indByEm ai lAddres s(new Em ail Address("bob@doe.com"));
}




                                                               Step4. “Test it…”
                                                                (Need Fixture…)
   Graph Database




Neo4j is the leading implementation of a property graph database. It is written
predominantly in Java and leverages a custom storage format and the facilities of the Java
Transaction Architecture (JTA) to provide XA transactions.
Neo4j integrates a transactional, pluggable indexing subsystem that uses Lucene as the
default. The index is used primarily to locate starting points for traversals. Its second use
is to support unique entity creation.
   Cypher statement




With the declarative Cypher query language, Neo4j makes it easier to get started for
everyone who knows SQL from working with relational databases.
enabling users to define sophisticated queries like “find me all the customers who have
friends who have recently bought similar products.”
Like other query languages, it supports filtering, grouping, and paging. Cypher allows easy
creation, deletion, update, and graph construction.
   Graph Model                          Domain Model



                                                      AbstractEntity
                   Customer



                Address
                                                      <<NodeEntity>>
                                                          Customer


      Address



                                         <<NodeEntity>>
                                                                     EmailAddress
                                            Address




                   Step1. “Define Domain Model”
      AbstractDocument                                                        Customer
public abstract class AbstractEntity {                               @NodeEnti ty
                                                                     public class Customer extends AbstractEntity {
          @GraphId
          private Long id;                                                    private String firstName, lastName;

          public Long getId() {                                               @Indexed(unique = true)
                    return id;                                                private String emailAddress;
          }
                                                                              @Rel atedT o(type = "ADDRESS")
          @Override                                                           private Set<Address> addresses = new HashSet<Address>();
          public boolean equals(Object obj) {
                                                                              public Customer(String firstName, String lastName, String emailAddress) {
                     if (this == obj) {
                                           return true;                             Assert.hasText(firstName);
                     }                                                              Assert.hasText(lastName);
                                                                                    Assert.hasText(emailAddress);
                     if (id == null || obj == null || !
                     getClass().equals(obj.getClass())) {                          this.firstName = firstName;
                              return false;                                        this.lastName = lastName;
                     }                                                             this.emailAddress = emailAddress;
                      return id.equals(((AbstractEntity) obj).id);            }

             }                                                                protected Customer() {

          @Override                                                           }
          public int hashCode() {                                             …
                     return id == null ? 0 : id.hashCode();
          }
}




                                                   Step1. “Define Domain Model”
   Address                                                            CustomerRepository
@NodeEntity                                                                public interface CustomerRepository extends GraphRepository<Customer> {
public class Address extends AbstractEntity {
                                                                                   Customer findOne(Long id);
            private String street, city;
                                                                                   <C extends Customer> C save(C customer);

            public Address(String street, String city) {                           Customer findByEmailAddress(String emailAddress);
                      this.street = street;                                }
                      this.city = city;
             }

            public Address() {

            }
                                                                                     Step2. “Define Repository
 …                                                                                           Interface”
                                                                                        -Just only interface

           EmailAddress
public class EmailAddress {

private final String value;

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

protected EmailAddress() {

}
…




        Step1. “Define Domain Model”
    SpringConfig
@Configuration
@ComponentS can
@ImportResource("cl asspath:ME TA-INF /spring/spring-data-context.xml ")
@EnableT ransactionManagement
class ApplicationConfig {

           @Bean(destroyMethod = "shutdown")
           public GraphDatabaseService graphDatabaseService() {
                     //return new EmbeddedGraphDatabase("target/graph.db");
                     return new SpringRestGraphDatabase("http://localhost:7474/db/data");
           }
}



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd">


           <!--neo4j:config storeDi rectory="target/graph.db" /-->
           <neo4j :c onfig graphDatabaseService= "graphDatabaseService" />
           <neo4j :repositori es base-package="com. mckang.springdata.neo4j" />
</beans>




                                          Step3. “Configure Spring Beans”
     TestCase
@RunWith(SpringJUni t4ClassRunner.cl ass)
@Context Confi guration(classes = { TestConfig.class })                      @Test
public class TestMain {                                                      public void preventsDuplicateEmail() {

@Autowired                                                                        final EmailAddress email = new EmailAddress("dave@dmband.com");
CustomerReposi tory repository;                                                   Customer dave = repository.findByEmailAddress(email.getEmail());
                                                                                  Customer anotherDave = new Customer("Dave", "Matthews",dave.getEmailAddress());
@Autowired                                                                        repository.save(anotherDave);
DataSource dataSource;                                                       }

@Test                                                                        }
public void savesCustomerCorrectly() {

EmailAddress email = new EmailAddress("alicia@keys.com");
Customer alicia = new Customer("Alicia", "Keys",email.getEmail()); // todo
alicia.add(new Address("27 Broadway", "New York"));
Customer result = repository.save(alicia);
assertThat(result.getId(), is(notNullValue()));
}

@Test
public void readsCustomerByEmail() {

EmailAddress email = new EmailAddress("alicia@keys.com");
Customer alicia = new Customer("Alicia", "Keys",email.getEmail());
repository.save(alicia);
Customer result = repository.findByEmailAddress(email.getEmail());
assertThat(result, is(alicia));
}




                                                           Step4. “Test it…”
                                                            (Need Fixture…)

Spring data

  • 1.
  • 2.
    Overview  Spring Data is a high level SpringSource project whose purpose is to unify and ease the access to different kinds of persistence stores, both relational database systems and NoSQL data stores. Source http://www.infoq.com/articles/spring-data-intro Spring Data projects support the followings aspects: Templating Object/Datastore mapping Repository support
  • 3.
    Overview - Templates The main purpose of a Spring Data template (and all other Spring templates) is resource allocation and exception translation. A template offers store specific operations like saving, updating and deleting a single record or for executing queries or map/reduce jobs. But all these methods work only for the corresponding underlying datastore. MongoDb Template Configuration Example <!-- Connection to MongoDB server --> <mongo:db-factory host="localhost" port="27017" dbname="test" /> <!-- MongoDB Template --> <bean id="mongoTemplate“ class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> </bean>
  • 4.
    Overview - Object/Datastore Mapping With Spring Data, this support is extended to NoSQL datastores with object-like data structures. But these data structures can be quite different from each other, so it would be difficult to make up a common API for object/datastore mapping. Each type of datastore comes with its own set of annotations to provide the needed meta information for the mapping. JPA MongoDB Neo4j @Entity @Document( collection="usr") @NodeEntity @Table(name="TUSR") public class User {    public class User {    public class User {    @Id   private String id;    @GraphId   Long id;   @Id    private String id; @Field("fn")   private String name;     private String name;    @Column(name="fn")   private String name;    private Date lastLogin; private Date lastLogin; private Date lastLogin;  ... ... ... } } }
  • 5.
    Overview - Repository Support generic support for CRUD and paging , sorting by providing special parameters to the finder methods for all persistence stores The main advantages of repository support are: The developer writes a lot less boilerplate code Queries can by defined alongside the finder method and its documentation As a bonus, the JPQL queries are compiled as soon as the Spring context is assembled, not the first time you use the query, which makes it easier to detect syntax errors
  • 6.
    Data Model  Domain Model Customer Address <<MappedSuperClass>> AbstractEntity CREATE TABLE customer ( id BIGINT IDENTITY PRIMARY KEY, firstname VARCHAR(255), lastname VARCHAR(255), email_address VARCHAR(255)); <<Entity>> CREATE UNIQUE INDEX ix_customer_email Customer ON CUSTOMER (email_address ASC); CREATE TABLE address ( id BIGINT IDENTITY PRIMARY KEY, customer_id BIGINT CONSTRAINT address_customer_ref REFERENCES customer (id), street VARCHAR(255), city VARCHAR(255), <<Entity>> <<Embeddable>> country VARCHAR(255)); Address EmailAddress Step1. “Define Domain Model”
  • 7.
    AbstractEntity  Customer @M appedSupercl ass @Entity public class AbstractEntity { public class Customer extends AbstractEntity { @Id private String firstname, lastname; @GeneratedValue(strategy = GenerationT ype. AUTO) private Long id; @Col umn(unique = true) private EmailAddress emailAddress; public Long getId() { return id; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = } true) @JoinColumn(nam e = "custom er_id") public boolean equals(Object obj) { private Set<Address> addresses = new HashSet<Address>(); if (this == obj) { return true; public Customer(String firstname, String lastname) { } Assert.hasText(firstname); if (this.id == null || obj == null || ! Assert.hasText(lastname); (this.getClass().equals(obj.getClass()))) { return false; this.firstname = firstname; } this.lastname = lastname; } AbstractEntity that = (AbstractEntity) obj; protected Customer() { return this.id.equals(that.getId()); } } public int hashCode() { public void add(Address address) { return id == null ? 0 : id.hashCode(); } Assert.notNull(address); } this.addresses.add(address); } … @MappedSuperclass to express that it is not a If there were demand to customize the names of the managed columns to which the properties would be persisted, entity class on its own but rather will be extended you could use the @Column annotation. by entity classes. Step1. “Define Domain Model”
  • 8.
    Address  CustomerRepository @Entity public interface CustomerRepository public class Address extends AbstractEntity { ext ends CrudRepos itory<Customer, Long> { Customer findByEmailAddress(EmailAddress emailAddress); private String street, city, country; Customer findById(Long id); List<Customer> findAll(); public Address(String street, String city, String country) { } Assert.hasText(street, "Street must not be null or empty!"); Assert.hasText(city, "City must not be null or empty!"); Assert.hasText(country, "Country must not be null or empty!"); this.street = street; this.city = city; this.country = country; Step2. “Define Repository } Interface” protected Address() { -Just only interface } …  EmailAddress @Em beddabl e public class EmailAddress { @Colum n(nam e = "email_address") private String value; public EmailAddress(String emailAddress) { Assert.isTrue(isValid(emailAddress), "Invalid email address!"); this.value = emailAddress; } the EmailAddress class is an @Embeddable, which protected EmailAddress() { will cause the persistence provider to flatten out all properties of it into the table of the } … surrounding class. Step1. “Define Domain Model”
  • 9.
    SpringConfig @Configuration @EnableT ransactionManagement @ComponentS can @EnableJ paReposi tories public class InfrastructureConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:sql/schema.sql") .addScript("classpath:sql/test-data.sql").build(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setDatabase(Database.HSQL); //vendorAdapter.setGenerateDdl(true); vendorAdapter.setShowSql(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan(getClass().getPackage().getName()); factory.setDataSource(dataSource()); return factory; } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory().getObject()); return txManager; } } Step3. “Configure Spring Beans”
  • 10.
    TestCase @RunWit h(SpringJUnit4Cl assRunner.class) @Test @Cont extConfiguration(classes = { TestConfig.cl ass }) public void saveNewCustomer() { @T ransactional Customer c = new Customer(); @Di rtiesContext //c.setFirstname("Sven"); public class TestMain { c.setLastname("Svensson"); c.setEmailAddress(new EmailAddress("sven@svensson.org")); @A utowired Address a = new Address("Storgaten 6", "Trosa", "Sweden"); CustomerRepository repository; c.add(a); repository.save(c); @Autowired System.out.println(repository.findAll()); DataSource dataSource; Customer result = repository.findOne(c.getId()); assertThat(result, is(notNullValue())); @Test //assertThat(result.getFirstName(), is("Sven")); public void testFindAll() { assertThat(result.getEmailAddress().toString(), is(notNullValue())); List< Custom er> results = reposi tory.findAl l(); } assertThat(results, is(notNullValue())); assertThat(results, hasSize(3)); assertThat(results.get(0), notNullValue()); @Test(expected = DataIntegrityViolationException.class) assertThat(results.get(1), notNullValue()); public void saveNewCustomerWithDuplicateEmail() { assertThat(results.get(2), notNullValue()); Customer c = new Customer("Bob","Doe"); } c.setEmailAddress(new EmailAddress("bob@doe.com")); Address a = new Address("66 Main St", "Middletown", "USA"); @Test c.add(a); public void testFindById() { repository.save(c); Customer res ult = repository.findOne(100L); } assertThat(result, is(notNullValue())); assertThat(result.getFirstname(), is("John")); @Test } public void deleteCustomer() { Customer c = repository.findOne(100L); @Test repository.delete(c); public void testFindByEmail() { Customer result = repository.findOne(100L); assertThat(result, is(nullValue())); Customer result = repository.fi ndByEm ail Address(new EmailA ddress("bob@doe.com")); assertThat(result, is(notNullValue())); } assertThat(result.getFirstname(), is("Bob")); } } Step4. “Test it…”
  • 11.
    Document Model  Domain Model Customer Email (*)Address AbstractDocument { firstname : "Dave", lastname : "Matthews", email : { email : "dave@dmband.com" <<Document>> }, addresses : [ Customer { street : "Broadway", city : "New York", country : "United States" } ] } <<Entity>> <<Embeddable>> Address EmailAddress Step1. “Define Domain Model”
  • 12.
    AbstractDocument  Customer public class AbstractDocument { @Document public class Customer extends AbstractDocument { @Id private BigInteger id; private String firstname, lastname; public BigInteger getId() { @Fi eld("em ail ") return id; @Indexed(unique = true) } private EmailAddress emailAddress; private Set<Address> addresses = new HashSet<Address>(); public boolean equals(Object obj) { public Customer(String firstname, String lastname) { if (this == obj) { return true; Assert.hasText(firstname); } Assert.hasText(lastname); if (this.id == null || obj == null || ! this.firstname = firstname; (this.getClass().equals(obj.getClass()))) { this.lastname = lastname; return false; } } protected Customer() { AbstractDocument that = (AbstractDocument) obj; } return this.id.equals(that.getId()); … } public int hashCode() { return id == null ? 0 : id.hashCode(); } } Step1. “Define Domain Model”
  • 13.
    Address  CustomerRepository public class Address { public interface CustomerRepository ext ends CrudRepos itory<Customer, Long> { private final String street, city, country; Customer findByEmailAddress(EmailAddress emailAddress); Customer findById(Long id); public Address(String street, String city, String country) { List<Customer> findAll(); } Assert.hasText(street, "Street must not be null or empty!"); Assert.hasText(city, "City must not be null or empty!"); Assert.hasText(country, "Country must not be null or empty!"); this.street = street; this.city = city; this.country = country; Step2. “Define Repository … } Interface” -Just only interface  EmailAddress public class EmailAddress { @F iel d("emai l") private final String value; public EmailAddress(String emailAddress) { Assert.isTrue(isValid(emailAddress), "Invalid email address!"); this.value = emailAddress; } protected EmailAddress() { } … Step1. “Define Domain Model”
  • 14.
    SpringConfig @Configuration @ComponentS can @EnableM ongoRepositories(baseP ackages="com.mck ang.springdata.mongo") class ApplicationConfig extends AbstractMongoConfiguration { @Autowired private List<Converter<?, ?>> converters; protected String getDatabaseName() { return "e-store"; } public Mongo mongo() throws Exception { Mongo mongo = new Mongo("127.0.0.1"); mongo.setWriteConcern(WriteConcern.FSYNC_SAFE); return mongo; } public CustomConversions customConversions() { return new CustomConversions(converters); } protected String get MappingBasePackage () { return "com.mckang.springdata.mongo"; } } Step3. “Configure Spring Beans”
  • 15.
    TestCase @RunWith(S pringJUnit4ClassRunner.class ) @Test @ContextConfigurati on(cl asses = { T es tConfi g.class }) public void saveNewCustomer() { @T ransactional Customer c = new Customer(); @DirtiesContext //c.setFirstname("Sven"); public class TestMain { c.setLastname("Svensson"); c.setEmailAddress(new EmailAddress("sven@svensson.org")); @Autowi red Address a = new Address("Storgaten 6", "Trosa", "Sweden"); Custom erRepository reposi tory; c.add(a); repository.save(c); @Autowired } DataSource dataSource; @Test @Test(expected = DataIntegrityViolationException.class) public void testFindAll() { public void saveNewCustomerWithDuplicateEmail() { List<Custom er> results = repository.f indAll (); Customer c = new Customer("Bob","Doe"); assertThat(results, is(notNullValue())); c.setEmailAddress(new EmailAddress("bob@doe.com")); assertThat(results, hasSize(3)); Address a = new Address("66 Main St", "Middletown", "USA"); assertThat(results.get(0), notNullValue()); c.add(a); assertThat(results.get(1), notNullValue()); repository.save(c); assertThat(results.get(2), notNullValue()); } } @Test @Test public void deleteCustomer() { public void testFindById() { Customer c = repository.findOne(100L); Custom er result = repos it ory.findOne(100L); repository.delete(c); assertThat(result, is(notNullValue())); } assertThat(result.getFirstname(), is("John")); } } @Test public void testFindByEmail() { Customer result = repository.f indByEm ai lAddres s(new Em ail Address("bob@doe.com")); } Step4. “Test it…” (Need Fixture…)
  • 16.
    Graph Database Neo4j is the leading implementation of a property graph database. It is written predominantly in Java and leverages a custom storage format and the facilities of the Java Transaction Architecture (JTA) to provide XA transactions. Neo4j integrates a transactional, pluggable indexing subsystem that uses Lucene as the default. The index is used primarily to locate starting points for traversals. Its second use is to support unique entity creation.
  • 17.
    Cypher statement With the declarative Cypher query language, Neo4j makes it easier to get started for everyone who knows SQL from working with relational databases. enabling users to define sophisticated queries like “find me all the customers who have friends who have recently bought similar products.” Like other query languages, it supports filtering, grouping, and paging. Cypher allows easy creation, deletion, update, and graph construction.
  • 19.
    Graph Model  Domain Model AbstractEntity Customer Address <<NodeEntity>> Customer Address <<NodeEntity>> EmailAddress Address Step1. “Define Domain Model”
  • 20.
    AbstractDocument  Customer public abstract class AbstractEntity { @NodeEnti ty public class Customer extends AbstractEntity { @GraphId private Long id; private String firstName, lastName; public Long getId() { @Indexed(unique = true) return id; private String emailAddress; } @Rel atedT o(type = "ADDRESS") @Override private Set<Address> addresses = new HashSet<Address>(); public boolean equals(Object obj) { public Customer(String firstName, String lastName, String emailAddress) { if (this == obj) { return true; Assert.hasText(firstName); } Assert.hasText(lastName); Assert.hasText(emailAddress); if (id == null || obj == null || ! getClass().equals(obj.getClass())) { this.firstName = firstName; return false; this.lastName = lastName; } this.emailAddress = emailAddress; return id.equals(((AbstractEntity) obj).id); } } protected Customer() { @Override } public int hashCode() { … return id == null ? 0 : id.hashCode(); } } Step1. “Define Domain Model”
  • 21.
    Address  CustomerRepository @NodeEntity public interface CustomerRepository extends GraphRepository<Customer> { public class Address extends AbstractEntity { Customer findOne(Long id); private String street, city; <C extends Customer> C save(C customer); public Address(String street, String city) { Customer findByEmailAddress(String emailAddress); this.street = street; } this.city = city; } public Address() { } Step2. “Define Repository … Interface” -Just only interface  EmailAddress public class EmailAddress { private final String value; public EmailAddress(String emailAddress) { Assert.isTrue(isValid(emailAddress), "Invalid email address!"); this.value = emailAddress; } protected EmailAddress() { } … Step1. “Define Domain Model”
  • 22.
    SpringConfig @Configuration @ComponentS can @ImportResource("cl asspath:ME TA-INF /spring/spring-data-context.xml ") @EnableT ransactionManagement class ApplicationConfig { @Bean(destroyMethod = "shutdown") public GraphDatabaseService graphDatabaseService() { //return new EmbeddedGraphDatabase("target/graph.db"); return new SpringRestGraphDatabase("http://localhost:7474/db/data"); } } <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd"> <!--neo4j:config storeDi rectory="target/graph.db" /--> <neo4j :c onfig graphDatabaseService= "graphDatabaseService" /> <neo4j :repositori es base-package="com. mckang.springdata.neo4j" /> </beans> Step3. “Configure Spring Beans”
  • 23.
    TestCase @RunWith(SpringJUni t4ClassRunner.cl ass) @Context Confi guration(classes = { TestConfig.class }) @Test public class TestMain { public void preventsDuplicateEmail() { @Autowired final EmailAddress email = new EmailAddress("dave@dmband.com"); CustomerReposi tory repository; Customer dave = repository.findByEmailAddress(email.getEmail()); Customer anotherDave = new Customer("Dave", "Matthews",dave.getEmailAddress()); @Autowired repository.save(anotherDave); DataSource dataSource; } @Test } public void savesCustomerCorrectly() { EmailAddress email = new EmailAddress("alicia@keys.com"); Customer alicia = new Customer("Alicia", "Keys",email.getEmail()); // todo alicia.add(new Address("27 Broadway", "New York")); Customer result = repository.save(alicia); assertThat(result.getId(), is(notNullValue())); } @Test public void readsCustomerByEmail() { EmailAddress email = new EmailAddress("alicia@keys.com"); Customer alicia = new Customer("Alicia", "Keys",email.getEmail()); repository.save(alicia); Customer result = repository.findByEmailAddress(email.getEmail()); assertThat(result, is(alicia)); } Step4. “Test it…” (Need Fixture…)