Fixes JIRA issue SGF-277 - OQL Join in Repository Interface.

This commit is contained in:
John Blum
2014-04-28 14:21:45 -07:00
parent edca5232a4
commit 8fd0b0bf6d
14 changed files with 470 additions and 39 deletions

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;
import org.springframework.util.Assert;
/**
* The Account class is an abstract data type (ADT) for modeling customer accounts.
*
* @author John Blum
* @see org.springframework.data.gemfire.mapping.Region
* @since 1.0.0
*/
@Region("Accounts")
@SuppressWarnings("unused")
public class Account {
@Id
private Long id;
private Long customerId;
private String number;
public Account(final Long customerId) {
Assert.notNull(customerId, "The Customer ID to which this Account is associated cannot be null!");
this.customerId = customerId;
}
public Account(final Customer customer) {
this(customer.getId());
}
public Account(final Long customerId, final String number) {
this(customerId);
this.number = number;
}
public Account(final Customer customer, final String number) {
this(customer);
this.number = number;
}
public Account(final Long accountId, final Long customerId) {
this(customerId);
this.id = accountId;
}
public Account(final Long accountId, final Customer customer) {
this(customer);
this.id = accountId;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(final Long customerId) {
this.customerId = customerId;
}
public String getNumber() {
return number;
}
public void setNumber(final String number) {
this.number = number;
}
@Override
public String toString() {
return String.format("Customer (%1$d) Account (%2$d) #(%3$s)", getCustomerId(), getId(), getNumber());
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import org.springframework.data.gemfire.repository.GemfireRepository;
/**
* The AccountsRepository class is a Data Access Object (DAO) for accessing and performing persistent operations on
* Account objects.
*
* @author John Blum
* @see org.springframework.data.gemfire.repository.sample.Account
* @see org.springframework.data.gemfire.repository.GemfireRepository
* @since 1.0.0
*/
@SuppressWarnings("unused")
public interface AccountRepository extends GemfireRepository<Account, Long> {
}

View File

@@ -38,7 +38,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @since 1.4.0
* @link https://github.com/spring-projects/spring-data-gemfire/pull/55
*/
@ContextConfiguration("AnimalRepositoryTest-context.xml")
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SuppressWarnings("unused")
public class AnimalRepositoryTest {

View File

@@ -29,7 +29,7 @@ public interface CatRepository extends GemfireRepository<Animal, Long> {
Animal findByName(String name);
@Query("SELECT * FROM /Animals x WHERE x.name = $1")
@Query("SELECT * FROM /Cats x WHERE x.name = $1")
Animal findBy(String name);
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;
import org.springframework.util.ObjectUtils;
/**
* The Customer class is a class abstraction modeling a Customer.
*
* @author John Blum
* @see org.springframework.data.annotation.Id
* @see org.springframework.data.gemfire.mapping.Region
* @since 1.0.0
*/
@SuppressWarnings("unused")
@Region("Customers")
public class Customer {
@Id
private Long id;
private String firstName;
private String lastName;
public Customer() {
}
public Customer(final Long id) {
this.id = id;
}
public Customer(final String firstName, final String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
protected static boolean equalsIgnoreNull(final Object obj1, final Object obj2) {
return (obj1 == null ? obj2 == null : obj1.equals(obj2));
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Customer)) {
return false;
}
final Customer that = (Customer) obj;
return equalsIgnoreNull(this.getId(), that.getId())
&& ObjectUtils.nullSafeEquals(this.getFirstName(), that.getFirstName())
&& ObjectUtils.nullSafeEquals(this.getLastName(), that.getLastName());
}
protected static int hashCodeIgnoreNull(final Object obj) {
return (obj != null ? obj.hashCode() : 0);
}
@Override
public int hashCode() {
int hashValue = 17;
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getId());
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getFirstName());
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getLastName());
return hashValue;
}
@Override
public String toString() {
return String.format("%1$s %2$s", getFirstName(), getLastName());
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import java.util.List;
import org.springframework.data.gemfire.repository.GemfireRepository;
import org.springframework.data.gemfire.repository.Query;
/**
* The CustomerRepository class is a Data Access Object (DAO) for accessing and performing persistent operations on
* Customer objects.
*
* @author John Blum
* @see org.springframework.data.gemfire.repository.sample.Customer
* @see org.springframework.data.gemfire.repository.GemfireRepository
* @since 1.0.0
*/
@SuppressWarnings("unused")
public interface CustomerRepository extends GemfireRepository<Customer, Long> {
@Query("SELECT DISTINCT c FROM /Customers c, /Accounts a WHERE c.id = a.customerId")
List<Customer> findCustomersWithAccounts();
}

View File

@@ -29,7 +29,7 @@ public interface DogRepository extends GemfireRepository<Animal, Long> {
Animal findByName(String name);
@Query("SELECT * FROM /Animals x WHERE x.name = $1")
@Query("SELECT * FROM /Dogs x WHERE x.name = $1")
Animal findBy(String name);
}

View File

@@ -28,10 +28,10 @@ import org.springframework.data.gemfire.repository.Query;
*/
public interface PersonRepository extends GemfireRepository<Person, Long> {
@Query("SELECT * FROM /Person p WHERE p.firstname = $1")
@Query("SELECT * FROM /simple p WHERE p.firstname = $1")
Collection<Person> findByFirstnameAnnotated(String firstname);
@Query("SELECT * FROM /Person p WHERE p.firstname IN SET $1")
@Query("SELECT * FROM /simple p WHERE p.firstname IN SET $1")
Collection<Person> findByFirstnamesAnnotated(Collection<String> firstnames);
Collection<Person> findByFirstname(String firstname);

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.repository.sample;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* The RepositoryQueriesWithJoinsTest class is a test suite of test cases testing the use of JOINS between 2 Regions
* in GemFire OQL queries (SELECT statements).
*
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since 1.0.0
*/
@ContextConfiguration("repositoryQueriesWithJoins.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@SuppressWarnings("unused")
public class RepositoryQueriesWithJoinsIntegrationTest {
private static final AtomicLong ID_SEQUENCE = new AtomicLong(0l);
@Autowired
private AccountRepository accountRepo;
@Autowired
private CustomerRepository customerRepo;
protected Account createAccount(final Customer customer, final String number) {
Account account = new Account(ID_SEQUENCE.incrementAndGet(), customer);
account.setNumber(number);
return account;
}
protected Customer createCustomer(final String firstName, final String lastName) {
Customer customer = new Customer(firstName, lastName);
customer.setId(ID_SEQUENCE.incrementAndGet());
return customer;
}
@Test
public void testJoinQueries() {
Customer jonDoe = customerRepo.save(createCustomer("Jon", "Doe"));
Customer janeDoe = customerRepo.save(createCustomer("Jane", "Doe"));
Customer jackHandy = customerRepo.save(createCustomer("Jack", "Handy"));
Account jonAccountOne = accountRepo.save(createAccount(jonDoe, "1"));
Account jonAccountTwo = accountRepo.save(createAccount(jonDoe, "2"));
Account janeAccount = accountRepo.save(createAccount(janeDoe, "1"));
List<Customer> actualCustomersWithAccounts = customerRepo.findCustomersWithAccounts();
List<Customer> expectedCustomersWithAccounts = Arrays.asList(jonDoe, janeDoe);
assertNotNull(actualCustomersWithAccounts);
assertFalse(String.format("Expected Customers (%1$s)!", expectedCustomersWithAccounts),
actualCustomersWithAccounts.isEmpty());
assertEquals(String.format("Expected Customers (%1$s); but was (%2$s)!", expectedCustomersWithAccounts, actualCustomersWithAccounts),
2, actualCustomersWithAccounts.size());
assertTrue(String.format("Expected Customers (%1$s); but was (%2$s)!", expectedCustomersWithAccounts, actualCustomersWithAccounts),
actualCustomersWithAccounts.containsAll(expectedCustomersWithAccounts));
}
}