DATACOUCH-140 - Use Converter to match query params and stored values.

When deriving a query, use the CouchbaseConverter to transform the parameters for fields that would be converted upon storage.

Reworked the DateConverters so that reading conversion is done from any Number (since N1QL may return longs in Double scientific notation for example).
This commit is contained in:
Simon Baslé
2015-07-16 16:09:50 +02:00
parent 4f0ba9d215
commit e0972d57b9
12 changed files with 380 additions and 39 deletions

View File

@@ -0,0 +1,78 @@
package org.springframework.data.couchbase.repository;
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.couchbase.core.mapping.Field;
/**
* An entity used to test conversion of parameters in query derivations.
*
* @author Simon Baslé
*/
public class Party {
@Id
private final String key;
private final String name;
@Field("desc")
private final String description;
private final Date eventDate;
private final long attendees;
public Party(String key, String name, String description, Date eventDate, long attendees) {
this.key = key;
this.name = name;
this.description = description;
this.eventDate = eventDate;
this.attendees = attendees;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Date getEventDate() {
return eventDate;
}
public long getAttendees() {
return attendees;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Party party = (Party) o;
return key.equals(party.key);
}
@Override
public int hashCode() {
return key.hashCode();
}
@Override
public String toString() {
return "Party{" +
"name='" + name + '\'' +
", eventDate=" + eventDate +
'}';
}
}

View File

@@ -0,0 +1,20 @@
package org.springframework.data.couchbase.repository;
import java.util.Date;
import java.util.List;
import org.springframework.data.couchbase.core.view.View;
/**
* @author Simon Baslé
*/
public interface PartyRepository extends CouchbaseRepository<Party, String> {
List<Party> findByAttendeesGreaterThanEqual(int minAttendees);
List<Party> findByEventDateIs(Date targetDate);
@View(designDocument = "party", viewName = "byDate")
List<Party> findFirst3ByEventDateGreaterThanEqual(Date targetDate);
}

View File

@@ -0,0 +1,61 @@
package org.springframework.data.couchbase.repository;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.PersistTo;
import com.couchbase.client.java.ReplicateTo;
import com.couchbase.client.java.view.DefaultView;
import com.couchbase.client.java.view.DesignDocument;
import com.couchbase.client.java.view.View;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
/**
* @author Simon Baslé
*/
public class QueryDerivationConversionListener extends DependencyInjectionTestExecutionListener {
@Override
public void beforeTestClass(final TestContext testContext) throws Exception {
Bucket client = (Bucket) testContext.getApplicationContext().getBean("couchbaseBucket");
populateTestData(client);
createAndWaitForDesignDocs(client);
}
private void populateTestData(Bucket client) {
CouchbaseTemplate template = new CouchbaseTemplate(client);
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.DAY_OF_MONTH, 10);
cal.set(Calendar.MONTH, Calendar.JANUARY);
for (int i = 0; i < 12; i++) {
Party p = new Party("testparty-" + i, "party like it's 199" + i,
"An awesome party, 90's themed, every 10 of the month",
cal.getTime(), 100 + i * 10);
template.save(p, PersistTo.MASTER, ReplicateTo.NONE);
cal.roll(Calendar.MONTH, true);
}
cal.clear();
cal.set(Calendar.YEAR, 1990);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 01);
template.save(new Party("aTestParty", "New Year's Eve 90", "Happy New Year", cal.getTime(), 1230000));
}
private void createAndWaitForDesignDocs(Bucket client) {
String mapFunction = "function (doc, meta) { if(doc._class == \"" + Party.class.getName() + "\") { emit(doc.eventDate, null); } }";
View view = DefaultView.create("byDate", mapFunction, "_count");
List<View> views = Collections.singletonList(view);
DesignDocument designDoc = DesignDocument.create("party", views);
client.bucketManager().upsertDesignDocument(designDoc);
}
}

View File

@@ -0,0 +1,89 @@
package org.springframework.data.couchbase.repository;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.document.JsonDocument;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.couchbase.IntegrationTestApplicationConfig;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.repository.support.CouchbaseRepositoryFactory;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Simon Baslé
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = IntegrationTestApplicationConfig.class)
@TestExecutionListeners(QueryDerivationConversionListener.class)
public class QueryDerivationConversionTests {
@Autowired
private Bucket client;
@Autowired
private CouchbaseTemplate template;
private PartyRepository repository;
@Before
public void setup() throws Exception {
RepositoryFactorySupport factory = new CouchbaseRepositoryFactory(template);
repository = factory.getRepository(PartyRepository.class);
}
@Test
public void testConvertsDateParameterInN1qlQuery() {
Party partyApril = repository.findOne("testparty-3");
assertNotNull(partyApril);
System.out.println(partyApril);
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2015, Calendar.APRIL, 10);
Date find = cal.getTime();
List<Party> parties = repository.findByEventDateIs(find);
assertNotNull(parties);
assertEquals(1, parties.size());
assertEquals(find, parties.get(0).getEventDate());
JsonDocument doc = client.get(parties.get(0).getKey());
assertEquals(find.getTime(), doc.content().get("eventDate"));
}
@Test
public void testAcceptLongParameterInN1qlQuery() {
List<Party> newYear90 = repository.findByAttendeesGreaterThanEqual(1200000);
assertNotNull(newYear90);
assertEquals(1, newYear90.size());
assertEquals("aTestParty", newYear90.get(0).getKey());
}
@Test
public void testConvertDateParameterInViewQuery() {
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2015, Calendar.AUGUST, 12);
Date find = cal.getTime();
List<Party> afterSummerParties = repository.findFirst3ByEventDateGreaterThanEqual(find);
assertNotNull(afterSummerParties);
assertEquals(3, afterSummerParties.size());
for (Party afterSummerParty : afterSummerParties) {
assert(afterSummerParty.getEventDate().after(find));
}
}
}