Merge branch 'develop'
This commit is contained in:
commit
9675c10772
116 changed files with 4576 additions and 3959 deletions
|
@ -1,9 +1,9 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import org.apache.commons.lang3.SerializationUtils;
|
||||||
|
|
||||||
import com.google.common.primitives.Primitives;
|
import com.google.common.primitives.Primitives;
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T get(Getter<T> getter, Class<?> returnType) {
|
public <T> T get(Getter<T> getter, Class<?> returnType) {
|
||||||
return (T) get(this.<T>methodNameFor(getter), returnType);
|
return (T) get(this.<T>methodNameFor(getter), returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T get(String key, Class<?> returnType) {
|
public <T> T get(String key, Class<?> returnType) {
|
||||||
T value = (T) backingMap.get(key);
|
T value = (T) backingMap.get(key);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -51,17 +51,27 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
||||||
|
|
||||||
return (T) type.getDefaultValue();
|
return (T) type.getDefaultValue();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Collections fetched from the entityMap
|
||||||
|
if (value instanceof Collection) {
|
||||||
|
try {
|
||||||
|
value = MappingUtil.<T>clone(value);
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
// TODO(gburd): deep?shallow? copy of List, Map, Set to a mutable collection.
|
||||||
|
value = (T) SerializationUtils.<Serializable>clone((Serializable) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Object set(Getter<T> getter, Object value) {
|
public <T> Object set(Getter<T> getter, Object value) {
|
||||||
return set(this.<T>methodNameFor(getter), value);
|
return set(this.<T>methodNameFor(getter), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object set(String key, Object value) {
|
public Object set(String key, Object value) {
|
||||||
if (key == null || value == null) {
|
if (key == null || value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -71,11 +81,11 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T mutate(Getter<T> getter, T value) {
|
public <T> T mutate(Getter<T> getter, T value) {
|
||||||
return (T) mutate(this.<T>methodNameFor(getter), value);
|
return (T) mutate(this.<T>methodNameFor(getter), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object mutate(String key, Object value) {
|
public Object mutate(String key, Object value) {
|
||||||
Objects.requireNonNull(key);
|
Objects.requireNonNull(key);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
|
|
@ -24,14 +24,16 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
import com.google.common.base.Stopwatch;
|
||||||
import com.google.common.collect.Table;
|
import com.google.common.collect.Table;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import net.helenus.core.cache.Facet;
|
import net.helenus.core.cache.Facet;
|
||||||
|
import net.helenus.core.operation.Operation;
|
||||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||||
import net.helenus.mapping.value.ColumnValueProvider;
|
import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
|
import net.helenus.support.Either;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public abstract class AbstractSessionOperations {
|
public abstract class AbstractSessionOperations {
|
||||||
|
@ -60,7 +62,7 @@ public abstract class AbstractSessionOperations {
|
||||||
|
|
||||||
public PreparedStatement prepare(RegularStatement statement) {
|
public PreparedStatement prepare(RegularStatement statement) {
|
||||||
try {
|
try {
|
||||||
log(statement, false);
|
logStatement(statement, false);
|
||||||
return currentSession().prepare(statement);
|
return currentSession().prepare(statement);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw translateException(e);
|
throw translateException(e);
|
||||||
|
@ -69,7 +71,7 @@ public abstract class AbstractSessionOperations {
|
||||||
|
|
||||||
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
|
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
|
||||||
try {
|
try {
|
||||||
log(statement, false);
|
logStatement(statement, false);
|
||||||
return currentSession().prepareAsync(statement);
|
return currentSession().prepareAsync(statement);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw translateException(e);
|
throw translateException(e);
|
||||||
|
@ -77,37 +79,47 @@ public abstract class AbstractSessionOperations {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSet execute(Statement statement, boolean showValues) {
|
public ResultSet execute(Statement statement, boolean showValues) {
|
||||||
return executeAsync(statement, showValues).getUninterruptibly();
|
return execute(statement, null, null, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSet execute(Statement statement, Stopwatch timer, boolean showValues) {
|
||||||
|
return execute(statement, null, timer, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSet execute(Statement statement, UnitOfWork uow, boolean showValues) {
|
||||||
|
return execute(statement, uow, null, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSet execute(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
|
||||||
|
return executeAsync(statement, uow, timer, showValues).getUninterruptibly();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSetFuture executeAsync(Statement statement, boolean showValues) {
|
public ResultSetFuture executeAsync(Statement statement, boolean showValues) {
|
||||||
|
return executeAsync(statement, null, null, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSetFuture executeAsync(Statement statement, Stopwatch timer, boolean showValues) {
|
||||||
|
return executeAsync(statement, null, timer, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSetFuture executeAsync(Statement statement, UnitOfWork uow, boolean showValues) {
|
||||||
|
return executeAsync(statement, uow, null, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSetFuture executeAsync(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
|
||||||
try {
|
try {
|
||||||
log(statement, showValues);
|
logStatement(statement, showValues);
|
||||||
return currentSession().executeAsync(statement);
|
return currentSession().executeAsync(statement);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw translateException(e);
|
throw translateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(Statement statement, boolean showValues) {
|
private void logStatement(Statement statement, boolean showValues) {
|
||||||
if (LOG.isInfoEnabled()) {
|
|
||||||
LOG.info("Execute statement " + statement);
|
|
||||||
}
|
|
||||||
if (isShowCql()) {
|
if (isShowCql()) {
|
||||||
if (statement instanceof BuiltStatement) {
|
printCql(Operation.queryString(statement, showValues));
|
||||||
BuiltStatement builtStatement = (BuiltStatement) statement;
|
} else if (LOG.isInfoEnabled()) {
|
||||||
if (showValues) {
|
LOG.info("CQL> " + Operation.queryString(statement, showValues));
|
||||||
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
|
|
||||||
printCql(regularStatement.getQueryString());
|
|
||||||
} else {
|
|
||||||
printCql(builtStatement.getQueryString());
|
|
||||||
}
|
|
||||||
} else if (statement instanceof RegularStatement) {
|
|
||||||
RegularStatement regularStatement = (RegularStatement) statement;
|
|
||||||
printCql(regularStatement.getQueryString());
|
|
||||||
} else {
|
|
||||||
printCql(statement.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +131,7 @@ public abstract class AbstractSessionOperations {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mergeCache(Table<String, String, Object> cache) {
|
public void mergeCache(Table<String, String, Either<Object, List<Facet>>> uowCache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeException translateException(RuntimeException e) {
|
RuntimeException translateException(RuntimeException e) {
|
||||||
|
@ -139,4 +151,7 @@ public abstract class AbstractSessionOperations {
|
||||||
void printCql(String cql) {
|
void printCql(String cql) {
|
||||||
getPrintStream().println(cql);
|
getPrintStream().println(cql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cacheEvict(List<Facet> facets) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import static net.helenus.core.HelenusSession.deleted;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -29,6 +32,7 @@ import com.google.common.collect.TreeTraverser;
|
||||||
|
|
||||||
import net.helenus.core.cache.CacheUtil;
|
import net.helenus.core.cache.CacheUtil;
|
||||||
import net.helenus.core.cache.Facet;
|
import net.helenus.core.cache.Facet;
|
||||||
|
import net.helenus.support.Either;
|
||||||
|
|
||||||
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
||||||
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork<E>, AutoCloseable {
|
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork<E>, AutoCloseable {
|
||||||
|
@ -38,15 +42,18 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
|
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
|
||||||
private final HelenusSession session;
|
private final HelenusSession session;
|
||||||
private final AbstractUnitOfWork<E> parent;
|
private final AbstractUnitOfWork<E> parent;
|
||||||
// Cache:
|
private final Table<String, String, Either<Object, List<Facet>>> cache = HashBasedTable.create();
|
||||||
private final Table<String, String, Object> cache = HashBasedTable.create();
|
protected String purpose;
|
||||||
|
protected List<String> nestedPurposes = new ArrayList<String>();
|
||||||
|
protected int cacheHits = 0;
|
||||||
|
protected int cacheMisses = 0;
|
||||||
|
protected int databaseLookups = 0;
|
||||||
|
protected Stopwatch elapsedTime;
|
||||||
|
protected Map<String, Double> databaseTime = new HashMap<>();
|
||||||
|
protected double cacheLookupTime = 0.0;
|
||||||
private List<CommitThunk> postCommit = new ArrayList<CommitThunk>();
|
private List<CommitThunk> postCommit = new ArrayList<CommitThunk>();
|
||||||
private boolean aborted = false;
|
private boolean aborted = false;
|
||||||
private boolean committed = false;
|
private boolean committed = false;
|
||||||
private String purpose_;
|
|
||||||
private Stopwatch elapsedTime_;
|
|
||||||
private Stopwatch databaseTime_ = Stopwatch.createUnstarted();
|
|
||||||
private Stopwatch cacheLookupTime_ = Stopwatch.createUnstarted();
|
|
||||||
|
|
||||||
protected AbstractUnitOfWork(HelenusSession session, AbstractUnitOfWork<E> parent) {
|
protected AbstractUnitOfWork(HelenusSession session, AbstractUnitOfWork<E> parent) {
|
||||||
Objects.requireNonNull(session, "containing session cannot be null");
|
Objects.requireNonNull(session, "containing session cannot be null");
|
||||||
|
@ -56,13 +63,18 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stopwatch getExecutionTimer() {
|
public void addDatabaseTime(String name, Stopwatch amount) {
|
||||||
return databaseTime_;
|
Double time = databaseTime.get(name);
|
||||||
|
if (time == null) {
|
||||||
|
databaseTime.put(name, (double) amount.elapsed(TimeUnit.MICROSECONDS));
|
||||||
|
} else {
|
||||||
|
databaseTime.put(name, time + amount.elapsed(TimeUnit.MICROSECONDS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stopwatch getCacheLookupTimer() {
|
public void addCacheLookupTime(Stopwatch amount) {
|
||||||
return cacheLookupTime_;
|
cacheLookupTime += amount.elapsed(TimeUnit.MICROSECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,26 +85,72 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnitOfWork<E> begin() {
|
public synchronized UnitOfWork<E> begin() {
|
||||||
elapsedTime_ = Stopwatch.createStarted();
|
if (LOG.isInfoEnabled()) {
|
||||||
|
elapsedTime = Stopwatch.createStarted();
|
||||||
|
}
|
||||||
// log.record(txn::start)
|
// log.record(txn::start)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPurpose() {
|
||||||
|
return purpose;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnitOfWork setPurpose(String purpose) {
|
public UnitOfWork setPurpose(String purpose) {
|
||||||
purpose_ = purpose;
|
this.purpose = purpose;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logTimers(String what) {
|
@Override
|
||||||
double e = (double) elapsedTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0;
|
public void recordCacheAndDatabaseOperationCount(int cache, int ops) {
|
||||||
double d = (double) databaseTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0;
|
if (cache > 0) {
|
||||||
double c = (double) cacheLookupTime_.elapsed(TimeUnit.MICROSECONDS) / 1000.0;
|
cacheHits += cache;
|
||||||
double fd = (d / (e - c)) * 100.0;
|
} else {
|
||||||
double fc = (c / (e - d)) * 100.0;
|
cacheMisses += Math.abs(cache);
|
||||||
LOG.info(String.format("UOW(%s)%s %s (total: %.3fms cache: %.3fms %2.2f%% db: %.3fms %2.2f%%)", hashCode(),
|
}
|
||||||
(purpose_ == null ? "" : " " + purpose_), what, e, c, fc, d, fd));
|
if (ops > 0) {
|
||||||
|
databaseLookups += ops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String logTimers(String what) {
|
||||||
|
double e = (double) elapsedTime.elapsed(TimeUnit.MICROSECONDS) / 1000.0;
|
||||||
|
double d = 0.0;
|
||||||
|
double c = cacheLookupTime / 1000.0;
|
||||||
|
double fc = (c / e) * 100.0;
|
||||||
|
String database = "";
|
||||||
|
if (databaseTime.size() > 0) {
|
||||||
|
List<String> dbt = new ArrayList<>(databaseTime.size());
|
||||||
|
for (String name : databaseTime.keySet()) {
|
||||||
|
double t = databaseTime.get(name) / 1000.0;
|
||||||
|
d += t;
|
||||||
|
dbt.add(String.format("%s took %,.3fms %,2.2f%%", name, t, (t / e) * 100.0));
|
||||||
|
}
|
||||||
|
double fd = (d / e) * 100.0;
|
||||||
|
database = String.format(", %d quer%s (%,.3fms %,2.2f%% - %s)", databaseLookups,
|
||||||
|
(databaseLookups > 1) ? "ies" : "y", d, fd, String.join(", ", dbt));
|
||||||
|
}
|
||||||
|
String cache = "";
|
||||||
|
if (cacheLookupTime > 0) {
|
||||||
|
int cacheLookups = cacheHits + cacheMisses;
|
||||||
|
cache = String.format(" with %d cache lookup%s (%,.3fms %,2.2f%% - %,d hit, %,d miss)", cacheLookups,
|
||||||
|
cacheLookups > 1 ? "s" : "", c, fc, cacheHits, cacheMisses);
|
||||||
|
}
|
||||||
|
String da = "";
|
||||||
|
if (databaseTime.size() > 0 || cacheLookupTime > 0) {
|
||||||
|
double dat = d + c;
|
||||||
|
double daf = (dat / e) * 100;
|
||||||
|
da = String.format(" consuming %,.3fms for data access, or %,2.2f%% of total UOW time.", dat, daf);
|
||||||
|
}
|
||||||
|
String x = nestedPurposes.stream().distinct().collect(Collectors.joining(", "));
|
||||||
|
String n = nested.stream().map(uow -> String.valueOf(uow.hashCode())).collect(Collectors.joining(", "));
|
||||||
|
String s = String.format(Locale.US, "UOW(%s%s) %s in %,.3fms%s%s%s%s%s", hashCode(),
|
||||||
|
(nested.size() > 0 ? ", [" + n + "]" : ""), what, e, cache, database, da,
|
||||||
|
(purpose == null ? "" : " " + purpose), (nestedPurposes.isEmpty()) ? "" : ", " + x);
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyPostCommitFunctions() {
|
private void applyPostCommitFunctions() {
|
||||||
|
@ -101,7 +159,9 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
f.apply();
|
f.apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logTimers("committed");
|
if (LOG.isInfoEnabled()) {
|
||||||
|
LOG.info(logTimers("committed"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,15 +171,14 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
for (Facet facet : facets) {
|
for (Facet facet : facets) {
|
||||||
if (!facet.fixed()) {
|
if (!facet.fixed()) {
|
||||||
String columnName = facet.name() + "==" + facet.value();
|
String columnName = facet.name() + "==" + facet.value();
|
||||||
Object value = cache.get(tableName, columnName);
|
Either<Object, List<Facet>> eitherValue = cache.get(tableName, columnName);
|
||||||
if (value != null) {
|
if (eitherValue != null) {
|
||||||
if (result.isPresent() && result.get() != value) {
|
Object value = deleted;
|
||||||
// One facet matched, but another did not.
|
if (eitherValue.isLeft()) {
|
||||||
result = Optional.empty();
|
value = eitherValue.getLeft();
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
result = Optional.of(value);
|
|
||||||
}
|
}
|
||||||
|
result = Optional.of(value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,13 +191,46 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Facet> cacheEvict(List<Facet> facets) {
|
||||||
|
Either<Object, List<Facet>> deletedObjectFacets = Either.right(facets);
|
||||||
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
|
Optional<Object> optionalValue = cacheLookup(facets);
|
||||||
|
if (optionalValue.isPresent()) {
|
||||||
|
Object value = optionalValue.get();
|
||||||
|
|
||||||
|
for (Facet facet : facets) {
|
||||||
|
if (!facet.fixed()) {
|
||||||
|
String columnKey = facet.name() + "==" + facet.value();
|
||||||
|
// mark the value identified by the facet to `deleted`
|
||||||
|
cache.put(tableName, columnKey, deletedObjectFacets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// look for other row/col pairs that referenced the same object, mark them
|
||||||
|
// `deleted`
|
||||||
|
cache.columnKeySet().forEach(columnKey -> {
|
||||||
|
Either<Object, List<Facet>> eitherCachedValue = cache.get(tableName, columnKey);
|
||||||
|
if (eitherCachedValue.isLeft()) {
|
||||||
|
Object cachedValue = eitherCachedValue.getLeft();
|
||||||
|
if (cachedValue == value) {
|
||||||
|
cache.put(tableName, columnKey, deletedObjectFacets);
|
||||||
|
String[] parts = columnKey.split("==");
|
||||||
|
facets.add(new Facet<String>(parts[0], parts[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return facets;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cacheUpdate(Object value, List<Facet> facets) {
|
public void cacheUpdate(Object value, List<Facet> facets) {
|
||||||
Facet table = facets.remove(0);
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
String tableName = table.value().toString();
|
|
||||||
for (Facet facet : facets) {
|
for (Facet facet : facets) {
|
||||||
String columnName = facet.name() + "==" + facet.value();
|
if (!facet.fixed()) {
|
||||||
cache.put(tableName, columnName, value);
|
String columnName = facet.name() + "==" + facet.value();
|
||||||
|
cache.put(tableName, columnName, Either.left(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,21 +270,37 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
aborted = false;
|
aborted = false;
|
||||||
|
|
||||||
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
||||||
|
elapsedTime.stop();
|
||||||
|
|
||||||
// Merge UOW cache into parent's cache.
|
|
||||||
if (parent != null) {
|
|
||||||
parent.mergeCache(cache);
|
|
||||||
} else {
|
|
||||||
session.mergeCache(cache);
|
|
||||||
}
|
|
||||||
elapsedTime_.stop();
|
|
||||||
|
|
||||||
// Apply all post-commit functions for
|
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
|
// Apply all post-commit functions, this is the outter-most UnitOfWork.
|
||||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
traverser.postOrderTraversal(this).forEach(uow -> {
|
||||||
uow.applyPostCommitFunctions();
|
uow.applyPostCommitFunctions();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Merge our cache into the session cache.
|
||||||
|
session.mergeCache(cache);
|
||||||
|
|
||||||
return new PostCommitFunction(this, null);
|
return new PostCommitFunction(this, null);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Merge cache and statistics into parent if there is one.
|
||||||
|
parent.mergeCache(cache);
|
||||||
|
if (purpose != null) {
|
||||||
|
parent.nestedPurposes.add(purpose);
|
||||||
|
}
|
||||||
|
parent.cacheHits += cacheHits;
|
||||||
|
parent.cacheMisses += cacheMisses;
|
||||||
|
parent.databaseLookups += databaseLookups;
|
||||||
|
parent.cacheLookupTime += cacheLookupTime;
|
||||||
|
for (String name : databaseTime.keySet()) {
|
||||||
|
if (parent.databaseTime.containsKey(name)) {
|
||||||
|
double t = parent.databaseTime.get(name);
|
||||||
|
parent.databaseTime.put(name, t + databaseTime.get(name));
|
||||||
|
} else {
|
||||||
|
parent.databaseTime.put(name, databaseTime.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else {
|
// else {
|
||||||
|
@ -203,7 +311,7 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Explicitly discard the work and mark it as as such in the log. */
|
/* Explicitly discard the work and mark it as as such in the log. */
|
||||||
public void abort() {
|
public synchronized void abort() {
|
||||||
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
|
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
|
||||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
traverser.postOrderTraversal(this).forEach(uow -> {
|
||||||
uow.committed = false;
|
uow.committed = false;
|
||||||
|
@ -211,18 +319,22 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
});
|
});
|
||||||
// log.record(txn::abort)
|
// log.record(txn::abort)
|
||||||
// cache.invalidateSince(txn::start time)
|
// cache.invalidateSince(txn::start time)
|
||||||
if (!hasAborted()) {
|
if (LOG.isInfoEnabled()) {
|
||||||
elapsedTime_.stop();
|
if (elapsedTime.isRunning()) {
|
||||||
logTimers("aborted");
|
elapsedTime.stop();
|
||||||
|
}
|
||||||
|
LOG.info(logTimers("aborted"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeCache(Table<String, String, Object> from) {
|
private void mergeCache(Table<String, String, Either<Object, List<Facet>>> from) {
|
||||||
Table<String, String, Object> to = this.cache;
|
Table<String, String, Either<Object, List<Facet>>> to = this.cache;
|
||||||
from.rowMap().forEach((rowKey, columnMap) -> {
|
from.rowMap().forEach((rowKey, columnMap) -> {
|
||||||
columnMap.forEach((columnKey, value) -> {
|
columnMap.forEach((columnKey, value) -> {
|
||||||
if (to.contains(rowKey, columnKey)) {
|
if (to.contains(rowKey, columnKey)) {
|
||||||
to.put(rowKey, columnKey, CacheUtil.merge(to.get(rowKey, columnKey), from.get(rowKey, columnKey)));
|
// TODO(gburd):...
|
||||||
|
to.put(rowKey, columnKey, Either.left(CacheUtil.merge(to.get(rowKey, columnKey).getLeft(),
|
||||||
|
from.get(rowKey, columnKey).getLeft())));
|
||||||
} else {
|
} else {
|
||||||
to.put(rowKey, columnKey, from.get(rowKey, columnKey));
|
to.put(rowKey, columnKey, from.get(rowKey, columnKey));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
public class ConflictingUnitOfWorkException extends Exception {
|
public class ConflictingUnitOfWorkException extends Exception {
|
||||||
|
|
|
@ -23,39 +23,38 @@ import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.collect.Table;
|
import com.google.common.collect.Table;
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import net.helenus.core.cache.CacheUtil;
|
import net.helenus.core.cache.CacheUtil;
|
||||||
import net.helenus.core.cache.Facet;
|
import net.helenus.core.cache.Facet;
|
||||||
|
import net.helenus.core.cache.SessionCache;
|
||||||
import net.helenus.core.cache.UnboundFacet;
|
import net.helenus.core.cache.UnboundFacet;
|
||||||
import net.helenus.core.operation.*;
|
import net.helenus.core.operation.*;
|
||||||
import net.helenus.core.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
import net.helenus.mapping.value.*;
|
import net.helenus.mapping.value.*;
|
||||||
import net.helenus.support.DslPropertyException;
|
import net.helenus.support.*;
|
||||||
import net.helenus.support.Fun;
|
|
||||||
import net.helenus.support.Fun.Tuple1;
|
import net.helenus.support.Fun.Tuple1;
|
||||||
import net.helenus.support.Fun.Tuple2;
|
import net.helenus.support.Fun.Tuple2;
|
||||||
import net.helenus.support.Fun.Tuple6;
|
import net.helenus.support.Fun.Tuple6;
|
||||||
import net.helenus.support.HelenusException;
|
|
||||||
import net.helenus.support.HelenusMappingException;
|
|
||||||
|
|
||||||
public final class HelenusSession extends AbstractSessionOperations implements Closeable {
|
public final class HelenusSession extends AbstractSessionOperations implements Closeable {
|
||||||
|
|
||||||
private final int MAX_CACHE_SIZE = 10000;
|
public static final Object deleted = new Object();
|
||||||
private final int MAX_CACHE_EXPIRE_SECONDS = 600;
|
private static final Logger LOG = LoggerFactory.getLogger(HelenusSession.class);
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
private final CodecRegistry registry;
|
private final CodecRegistry registry;
|
||||||
|
@ -68,7 +67,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
private final SessionRepository sessionRepository;
|
private final SessionRepository sessionRepository;
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
private final boolean dropSchemaOnClose;
|
private final boolean dropSchemaOnClose;
|
||||||
private final Cache sessionCache;
|
private final SessionCache<String, Object> sessionCache;
|
||||||
private final RowColumnValueProvider valueProvider;
|
private final RowColumnValueProvider valueProvider;
|
||||||
private final StatementColumnValuePreparer valuePreparer;
|
private final StatementColumnValuePreparer valuePreparer;
|
||||||
private final Metadata metadata;
|
private final Metadata metadata;
|
||||||
|
@ -78,7 +77,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
HelenusSession(Session session, String usingKeyspace, CodecRegistry registry, boolean showCql,
|
HelenusSession(Session session, String usingKeyspace, CodecRegistry registry, boolean showCql,
|
||||||
PrintStream printStream, SessionRepositoryBuilder sessionRepositoryBuilder, Executor executor,
|
PrintStream printStream, SessionRepositoryBuilder sessionRepositoryBuilder, Executor executor,
|
||||||
boolean dropSchemaOnClose, ConsistencyLevel consistencyLevel, boolean defaultQueryIdempotency,
|
boolean dropSchemaOnClose, ConsistencyLevel consistencyLevel, boolean defaultQueryIdempotency,
|
||||||
Class<? extends UnitOfWork> unitOfWorkClass, MetricRegistry metricRegistry, Tracer tracer) {
|
Class<? extends UnitOfWork> unitOfWorkClass, SessionCache sessionCache, MetricRegistry metricRegistry,
|
||||||
|
Tracer tracer) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
||||||
this.usingKeyspace = Objects.requireNonNull(usingKeyspace,
|
this.usingKeyspace = Objects.requireNonNull(usingKeyspace,
|
||||||
|
@ -94,8 +94,11 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
this.metricRegistry = metricRegistry;
|
this.metricRegistry = metricRegistry;
|
||||||
this.zipkinTracer = tracer;
|
this.zipkinTracer = tracer;
|
||||||
|
|
||||||
this.sessionCache = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE)
|
if (sessionCache == null) {
|
||||||
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS).recordStats().build();
|
this.sessionCache = SessionCache.<String, Object>defaultCache();
|
||||||
|
} else {
|
||||||
|
this.sessionCache = sessionCache;
|
||||||
|
}
|
||||||
|
|
||||||
this.valueProvider = new RowColumnValueProvider(this.sessionRepository);
|
this.valueProvider = new RowColumnValueProvider(this.sessionRepository);
|
||||||
this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository);
|
this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository);
|
||||||
|
@ -184,7 +187,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
Object result = null;
|
Object result = null;
|
||||||
for (String[] combination : facetCombinations) {
|
for (String[] combination : facetCombinations) {
|
||||||
String cacheKey = tableName + "." + Arrays.toString(combination);
|
String cacheKey = tableName + "." + Arrays.toString(combination);
|
||||||
result = sessionCache.getIfPresent(cacheKey);
|
result = sessionCache.get(cacheKey);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -192,6 +195,16 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cacheEvict(List<Facet> facets) {
|
||||||
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
|
List<String[]> facetCombinations = CacheUtil.flattenFacets(facets);
|
||||||
|
for (String[] combination : facetCombinations) {
|
||||||
|
String cacheKey = tableName + "." + Arrays.toString(combination);
|
||||||
|
sessionCache.invalidate(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCache(Object pojo, List<Facet> facets) {
|
public void updateCache(Object pojo, List<Facet> facets) {
|
||||||
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
||||||
|
@ -200,14 +213,18 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
if (facet instanceof UnboundFacet) {
|
if (facet instanceof UnboundFacet) {
|
||||||
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
||||||
UnboundFacet.Binder binder = unboundFacet.binder();
|
UnboundFacet.Binder binder = unboundFacet.binder();
|
||||||
unboundFacet.getProperties().forEach(prop -> {
|
for (HelenusProperty prop : unboundFacet.getProperties()) {
|
||||||
|
Object value;
|
||||||
if (valueMap == null) {
|
if (valueMap == null) {
|
||||||
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
|
value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
|
||||||
binder.setValueForProperty(prop, value.toString());
|
if (value != null) {
|
||||||
|
binder.setValueForProperty(prop, value.toString());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
|
value = valueMap.get(prop.getPropertyName());
|
||||||
|
binder.setValueForProperty(prop, value.toString());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
if (binder.isBound()) {
|
if (binder.isBound()) {
|
||||||
boundFacets.add(binder.bind());
|
boundFacets.add(binder.bind());
|
||||||
}
|
}
|
||||||
|
@ -217,28 +234,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
}
|
}
|
||||||
String tableName = CacheUtil.schemaName(facets);
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
|
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
|
||||||
Object value = sessionCache.getIfPresent(pojo);
|
mergeAndUpdateCacheValues(pojo, tableName, facetCombinations);
|
||||||
Object mergedValue = null;
|
|
||||||
for (String[] combination : facetCombinations) {
|
|
||||||
String cacheKey = tableName + "." + Arrays.toString(combination);
|
|
||||||
if (value == null) {
|
|
||||||
sessionCache.put(cacheKey, pojo);
|
|
||||||
} else {
|
|
||||||
if (mergedValue == null) {
|
|
||||||
mergedValue = pojo;
|
|
||||||
} else {
|
|
||||||
mergedValue = CacheUtil.merge(value, pojo);
|
|
||||||
}
|
|
||||||
sessionCache.put(mergedValue, pojo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeCache(Table<String, String, Object> uowCache) {
|
public void mergeCache(Table<String, String, Either<Object, List<Facet>>> uowCache) {
|
||||||
List<Object> pojos = uowCache.values().stream().distinct().collect(Collectors.toList());
|
List<Object> items = uowCache.values().stream().filter(Either::isLeft).map(Either::getLeft).distinct()
|
||||||
for (Object pojo : pojos) {
|
.collect(Collectors.toList());
|
||||||
|
for (Object pojo : items) {
|
||||||
HelenusEntity entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo));
|
HelenusEntity entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo));
|
||||||
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
||||||
if (entity.isCacheable()) {
|
if (entity.isCacheable()) {
|
||||||
|
@ -249,7 +252,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
UnboundFacet.Binder binder = unboundFacet.binder();
|
UnboundFacet.Binder binder = unboundFacet.binder();
|
||||||
unboundFacet.getProperties().forEach(prop -> {
|
unboundFacet.getProperties().forEach(prop -> {
|
||||||
if (valueMap == null) {
|
if (valueMap == null) {
|
||||||
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
|
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
|
||||||
binder.setValueForProperty(prop, value.toString());
|
binder.setValueForProperty(prop, value.toString());
|
||||||
} else {
|
} else {
|
||||||
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
|
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
|
||||||
|
@ -262,24 +265,39 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
boundFacets.add(facet);
|
boundFacets.add(facet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String tableName = entity.getName().toCql();
|
|
||||||
// NOTE: should equal `String tableName = CacheUtil.schemaName(facets);`
|
// NOTE: should equal `String tableName = CacheUtil.schemaName(facets);`
|
||||||
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
|
List<String[]> facetCombinations = CacheUtil.flattenFacets(boundFacets);
|
||||||
Object value = sessionCache.getIfPresent(pojo);
|
String tableName = CacheUtil.schemaName(boundFacets);
|
||||||
Object mergedValue = null;
|
mergeAndUpdateCacheValues(pojo, tableName, facetCombinations);
|
||||||
for (String[] combination : facetCombinations) {
|
}
|
||||||
String cacheKey = tableName + "." + Arrays.toString(combination);
|
}
|
||||||
if (value == null) {
|
|
||||||
sessionCache.put(cacheKey, pojo);
|
List<List<Facet>> deletedFacetSets = uowCache.values().stream().filter(Either::isRight).map(Either::getRight)
|
||||||
} else {
|
.collect(Collectors.toList());
|
||||||
if (mergedValue == null) {
|
for (List<Facet> facets : deletedFacetSets) {
|
||||||
mergedValue = pojo;
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
} else {
|
List<String[]> combinations = CacheUtil.flattenFacets(facets);
|
||||||
mergedValue = CacheUtil.merge(value, pojo);
|
for (String[] combination : combinations) {
|
||||||
}
|
String cacheKey = tableName + "." + Arrays.toString(combination);
|
||||||
sessionCache.put(mergedValue, pojo);
|
sessionCache.invalidate(cacheKey);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeAndUpdateCacheValues(Object pojo, String tableName, List<String[]> facetCombinations) {
|
||||||
|
Object merged = null;
|
||||||
|
for (String[] combination : facetCombinations) {
|
||||||
|
String cacheKey = tableName + "." + Arrays.toString(combination);
|
||||||
|
Object value = sessionCache.get(cacheKey);
|
||||||
|
if (value == null) {
|
||||||
|
sessionCache.put(cacheKey, pojo);
|
||||||
|
} else {
|
||||||
|
if (merged == null) {
|
||||||
|
merged = pojo;
|
||||||
|
} else {
|
||||||
|
merged = CacheUtil.merge(value, pojo);
|
||||||
}
|
}
|
||||||
|
sessionCache.put(cacheKey, merged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,8 +306,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized UnitOfWork begin() {
|
public UnitOfWork begin() {
|
||||||
return begin(null);
|
return this.begin(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized UnitOfWork begin(UnitOfWork parent) {
|
public synchronized UnitOfWork begin(UnitOfWork parent) {
|
||||||
|
@ -297,6 +315,20 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
Class<? extends UnitOfWork> clazz = unitOfWorkClass;
|
Class<? extends UnitOfWork> clazz = unitOfWorkClass;
|
||||||
Constructor<? extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
|
Constructor<? extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
|
||||||
UnitOfWork uow = ctor.newInstance(this, parent);
|
UnitOfWork uow = ctor.newInstance(this, parent);
|
||||||
|
if (LOG.isInfoEnabled() && uow.getPurpose() == null) {
|
||||||
|
StringBuilder purpose = null;
|
||||||
|
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||||
|
int frame = 2;
|
||||||
|
if (trace[2].getMethodName().equals("begin")) {
|
||||||
|
frame = 3;
|
||||||
|
} else if (trace[2].getClassName().equals(unitOfWorkClass.getName())) {
|
||||||
|
frame = 3;
|
||||||
|
}
|
||||||
|
purpose = new StringBuilder().append(trace[frame].getClassName()).append(".")
|
||||||
|
.append(trace[frame].getMethodName()).append("(").append(trace[frame].getFileName()).append(":")
|
||||||
|
.append(trace[frame].getLineNumber()).append(")");
|
||||||
|
uow.setPurpose(purpose.toString());
|
||||||
|
}
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.addNestedUnitOfWork(uow);
|
parent.addNestedUnitOfWork(uow);
|
||||||
}
|
}
|
||||||
|
@ -470,6 +502,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
return new UpdateOperation<ResultSet>(this);
|
return new UpdateOperation<ResultSet>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <E> UpdateOperation<E> update(Object pojo) {
|
||||||
|
if (pojo instanceof MapExportable == false) {
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"update of objects that don't implement MapExportable is not yet supported");
|
||||||
|
}
|
||||||
|
return new UpdateOperation<E>(this, pojo);
|
||||||
|
}
|
||||||
|
|
||||||
public <E> UpdateOperation<E> update(Drafted<E> drafted) {
|
public <E> UpdateOperation<E> update(Drafted<E> drafted) {
|
||||||
if (drafted instanceof AbstractEntityDraft == false) {
|
if (drafted instanceof AbstractEntityDraft == false) {
|
||||||
throw new HelenusMappingException(
|
throw new HelenusMappingException(
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.datastax.driver.core.*;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
|
import net.helenus.core.cache.SessionCache;
|
||||||
import net.helenus.core.reflect.DslExportable;
|
import net.helenus.core.reflect.DslExportable;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusEntityType;
|
import net.helenus.mapping.HelenusEntityType;
|
||||||
|
@ -56,6 +57,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
private boolean dropUnusedIndexes = false;
|
private boolean dropUnusedIndexes = false;
|
||||||
private KeyspaceMetadata keyspaceMetadata;
|
private KeyspaceMetadata keyspaceMetadata;
|
||||||
private AutoDdl autoDdl = AutoDdl.UPDATE;
|
private AutoDdl autoDdl = AutoDdl.UPDATE;
|
||||||
|
private SessionCache sessionCache = null;
|
||||||
|
|
||||||
SessionInitializer(Session session) {
|
SessionInitializer(Session session) {
|
||||||
this.session = Objects.requireNonNull(session, "empty session");
|
this.session = Objects.requireNonNull(session, "empty session");
|
||||||
|
@ -123,6 +125,11 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SessionInitializer setSessionCache(SessionCache sessionCache) {
|
||||||
|
this.sessionCache = sessionCache;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ConsistencyLevel getDefaultConsistencyLevel() {
|
public ConsistencyLevel getDefaultConsistencyLevel() {
|
||||||
return consistencyLevel;
|
return consistencyLevel;
|
||||||
}
|
}
|
||||||
|
@ -243,8 +250,8 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
public synchronized HelenusSession get() {
|
public synchronized HelenusSession get() {
|
||||||
initialize();
|
initialize();
|
||||||
return new HelenusSession(session, usingKeyspace, registry, showCql, printStream, sessionRepository, executor,
|
return new HelenusSession(session, usingKeyspace, registry, showCql, printStream, sessionRepository, executor,
|
||||||
autoDdl == AutoDdl.CREATE_DROP, consistencyLevel, idempotent, unitOfWorkClass, metricRegistry,
|
autoDdl == AutoDdl.CREATE_DROP, consistencyLevel, idempotent, unitOfWorkClass, sessionCache,
|
||||||
zipkinTracer);
|
metricRegistry, zipkinTracer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
|
|
@ -25,8 +25,8 @@ import net.helenus.core.cache.Facet;
|
||||||
public interface UnitOfWork<X extends Exception> extends AutoCloseable {
|
public interface UnitOfWork<X extends Exception> extends AutoCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the beginning of a transactional section of work. Will write a record
|
* Marks the beginning of a transactional section of work. Will write a
|
||||||
* to the shared write-ahead log.
|
* recordCacheAndDatabaseOperationCount to the shared write-ahead log.
|
||||||
*
|
*
|
||||||
* @return the handle used to commit or abort the work.
|
* @return the handle used to commit or abort the work.
|
||||||
*/
|
*/
|
||||||
|
@ -59,10 +59,15 @@ public interface UnitOfWork<X extends Exception> extends AutoCloseable {
|
||||||
|
|
||||||
void cacheUpdate(Object pojo, List<Facet> facets);
|
void cacheUpdate(Object pojo, List<Facet> facets);
|
||||||
|
|
||||||
|
List<Facet> cacheEvict(List<Facet> facets);
|
||||||
|
|
||||||
|
String getPurpose();
|
||||||
UnitOfWork setPurpose(String purpose);
|
UnitOfWork setPurpose(String purpose);
|
||||||
|
|
||||||
Stopwatch getExecutionTimer();
|
void addDatabaseTime(String name, Stopwatch amount);
|
||||||
|
void addCacheLookupTime(Stopwatch amount);
|
||||||
|
|
||||||
Stopwatch getCacheLookupTimer();
|
// Cache > 0 means "cache hit", < 0 means cache miss.
|
||||||
|
void recordCacheAndDatabaseOperationCount(int cache, int database);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.core.annotation;
|
package net.helenus.core.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import net.helenus.core.ConflictingUnitOfWorkException;
|
import net.helenus.core.ConflictingUnitOfWorkException;
|
||||||
|
|
||||||
|
@ -11,7 +28,7 @@ import net.helenus.core.ConflictingUnitOfWorkException;
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface Retry {
|
public @interface Retry {
|
||||||
|
|
||||||
Class<? extends Exception>[] on() default ConflictingUnitOfWorkException.class;
|
Class<? extends Exception>[] on() default {ConflictingUnitOfWorkException.class, TimeoutException.class};
|
||||||
|
|
||||||
int times() default 3;
|
int times() default 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.core.aspect;
|
package net.helenus.core.aspect;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -73,7 +89,7 @@ public class RetryAspect {
|
||||||
return retryAnnotation;
|
return retryAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class[] argClasses = new Class[pjp.getArgs().length];
|
Class<?>[] argClasses = new Class[pjp.getArgs().length];
|
||||||
for (int i = 0; i < pjp.getArgs().length; i++) {
|
for (int i = 0; i < pjp.getArgs().length; i++) {
|
||||||
argClasses[i] = pjp.getArgs()[i].getClass();
|
argClasses[i] = pjp.getArgs()[i].getClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.cache;
|
package net.helenus.core.cache;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -23,7 +24,13 @@ import net.helenus.mapping.HelenusProperty;
|
||||||
public class BoundFacet extends Facet<String> {
|
public class BoundFacet extends Facet<String> {
|
||||||
private final Map<HelenusProperty, Object> properties;
|
private final Map<HelenusProperty, Object> properties;
|
||||||
|
|
||||||
BoundFacet(String name, Map<HelenusProperty, Object> properties) {
|
public BoundFacet(HelenusProperty property, Object value) {
|
||||||
|
super(property.getPropertyName(), value == null ? null : value.toString());
|
||||||
|
this.properties = new HashMap<HelenusProperty, Object>(1);
|
||||||
|
this.properties.put(property, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundFacet(String name, Map<HelenusProperty, Object> properties) {
|
||||||
super(name,
|
super(name,
|
||||||
(properties.keySet().size() > 1)
|
(properties.keySet().size() > 1)
|
||||||
? "[" + String.join(", ",
|
? "[" + String.join(", ",
|
||||||
|
|
|
@ -38,7 +38,22 @@ public class CacheUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object merge(Object to, Object from) {
|
public static Object merge(Object to, Object from) {
|
||||||
return to; // TODO(gburd): yeah...
|
if (to == from) {
|
||||||
|
return to;
|
||||||
|
} else {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* // TODO(gburd): take ttl and writeTime into account when merging. Map<String,
|
||||||
|
* Object> toValueMap = to instanceof MapExportable ? ((MapExportable)
|
||||||
|
* to).toMap() : null; Map<String, Object> fromValueMap = to instanceof
|
||||||
|
* MapExportable ? ((MapExportable) from).toMap() : null;
|
||||||
|
*
|
||||||
|
* if (toValueMap != null && fromValueMap != null) { for (String key :
|
||||||
|
* fromValueMap.keySet()) { if (toValueMap.containsKey(key) &&
|
||||||
|
* toValueMap.get(key) != fromValueMap.get(key)) { toValueMap.put(key,
|
||||||
|
* fromValueMap.get(key)); } } } return to;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String schemaName(List<Facet> facets) {
|
public static String schemaName(List<Facet> facets) {
|
||||||
|
|
44
src/main/java/net/helenus/core/cache/GuavaCache.java
vendored
Normal file
44
src/main/java/net/helenus/core/cache/GuavaCache.java
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.core.cache;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
|
||||||
|
public class GuavaCache<K, V> implements SessionCache<K, V> {
|
||||||
|
|
||||||
|
final Cache<K, V> cache;
|
||||||
|
|
||||||
|
GuavaCache(Cache<K, V> cache) {
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate(K key) {
|
||||||
|
cache.invalidate(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(K key) {
|
||||||
|
return cache.getIfPresent(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(K key, V value) {
|
||||||
|
cache.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
src/main/java/net/helenus/core/cache/SessionCache.java
vendored
Normal file
36
src/main/java/net/helenus/core/cache/SessionCache.java
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.core.cache;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
|
||||||
|
public interface SessionCache<K, V> {
|
||||||
|
|
||||||
|
static <K, V> SessionCache<K, V> defaultCache() {
|
||||||
|
int MAX_CACHE_SIZE = 10000;
|
||||||
|
int MAX_CACHE_EXPIRE_SECONDS = 600;
|
||||||
|
return new GuavaCache<K, V>(CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE)
|
||||||
|
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.expireAfterWrite(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS).recordStats().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate(K key);
|
||||||
|
V get(K key);
|
||||||
|
void put(K key, V value);
|
||||||
|
}
|
|
@ -15,10 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
import net.helenus.core.cache.Facet;
|
||||||
|
import net.helenus.core.cache.UnboundFacet;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>>
|
public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>>
|
||||||
extends
|
extends
|
||||||
|
@ -107,4 +109,39 @@ public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperati
|
||||||
}
|
}
|
||||||
ifFilters.add(filter);
|
ifFilters.add(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<Facet> bindFacetValues(List<Facet> facets) {
|
||||||
|
if (facets == null) {
|
||||||
|
return new ArrayList<Facet>();
|
||||||
|
}
|
||||||
|
List<Facet> boundFacets = new ArrayList<>();
|
||||||
|
Map<HelenusProperty, Filter> filterMap = new HashMap<>(filters.size());
|
||||||
|
filters.forEach(f -> filterMap.put(f.getNode().getProperty(), f));
|
||||||
|
|
||||||
|
for (Facet facet : facets) {
|
||||||
|
if (facet instanceof UnboundFacet) {
|
||||||
|
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
||||||
|
UnboundFacet.Binder binder = unboundFacet.binder();
|
||||||
|
if (filters != null) {
|
||||||
|
for (HelenusProperty prop : unboundFacet.getProperties()) {
|
||||||
|
|
||||||
|
Filter filter = filterMap.get(prop);
|
||||||
|
if (filter != null) {
|
||||||
|
Object[] postulates = filter.postulateValues();
|
||||||
|
for (Object p : postulates) {
|
||||||
|
binder.setValueForProperty(prop, p.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (binder.isBound()) {
|
||||||
|
boundFacets.add(binder.bind());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boundFacets.add(facet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boundFacets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
@ -31,15 +33,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
|
||||||
|
|
||||||
public abstract E transform(ResultSet resultSet);
|
public abstract E transform(ResultSet resultSet);
|
||||||
|
|
||||||
public boolean cacheable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PreparedOperation<E> prepare() {
|
public PreparedOperation<E> prepare() {
|
||||||
return new PreparedOperation<E>(prepareStatement(), this);
|
return new PreparedOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public E sync() {// throws TimeoutException {
|
public E sync() throws TimeoutException {
|
||||||
final Timer.Context context = requestLatency.time();
|
final Timer.Context context = requestLatency.time();
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = this.execute(sessionOps, null, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
ResultSet resultSet = this.execute(sessionOps, null, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
||||||
|
@ -50,7 +48,7 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public E sync(UnitOfWork uow) {// throws TimeoutException {
|
public E sync(UnitOfWork uow) throws TimeoutException {
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return sync();
|
return sync();
|
||||||
|
|
||||||
|
@ -67,11 +65,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
|
||||||
|
|
||||||
public CompletableFuture<E> async() {
|
public CompletableFuture<E> async() {
|
||||||
return CompletableFuture.<E>supplyAsync(() -> {
|
return CompletableFuture.<E>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,11 +77,11 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> ex
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return async();
|
return async();
|
||||||
return CompletableFuture.<E>supplyAsync(() -> {
|
return CompletableFuture.<E>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import static net.helenus.core.HelenusSession.deleted;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
|
@ -57,20 +61,25 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<E> sync() {// throws TimeoutException {
|
public Optional<E> sync() throws TimeoutException {
|
||||||
final Timer.Context context = requestLatency.time();
|
final Timer.Context context = requestLatency.time();
|
||||||
try {
|
try {
|
||||||
Optional<E> result = Optional.empty();
|
Optional<E> result = Optional.empty();
|
||||||
E cacheResult = null;
|
E cacheResult = null;
|
||||||
boolean updateCache = isSessionCacheable();
|
boolean updateCache = isSessionCacheable() && checkCache;
|
||||||
|
|
||||||
if (enableCache && isSessionCacheable()) {
|
if (checkCache && isSessionCacheable()) {
|
||||||
List<Facet> facets = bindFacetValues();
|
List<Facet> facets = bindFacetValues();
|
||||||
String tableName = CacheUtil.schemaName(facets);
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
cacheResult = (E) sessionOps.checkCache(tableName, facets);
|
cacheResult = (E) sessionOps.checkCache(tableName, facets);
|
||||||
if (cacheResult != null) {
|
if (cacheResult != null) {
|
||||||
result = Optional.of(cacheResult);
|
result = Optional.of(cacheResult);
|
||||||
updateCache = false;
|
updateCache = false;
|
||||||
|
sessionCacheHits.mark();
|
||||||
|
cacheHits.mark();
|
||||||
|
} else {
|
||||||
|
sessionCacheMiss.mark();
|
||||||
|
cacheMiss.mark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +104,7 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<E> sync(UnitOfWork<?> uow) {// throws TimeoutException {
|
public Optional<E> sync(UnitOfWork<?> uow) throws TimeoutException {
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return sync();
|
return sync();
|
||||||
|
|
||||||
|
@ -103,30 +112,59 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Optional<E> result = Optional.empty();
|
Optional<E> result = Optional.empty();
|
||||||
E cacheResult = null;
|
E cachedResult = null;
|
||||||
boolean updateCache = true;
|
final boolean updateCache;
|
||||||
|
|
||||||
if (enableCache) {
|
if (checkCache) {
|
||||||
Stopwatch timer = uow.getCacheLookupTimer();
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
timer.start();
|
try {
|
||||||
List<Facet> facets = bindFacetValues();
|
List<Facet> facets = bindFacetValues();
|
||||||
cacheResult = checkCache(uow, facets);
|
if (facets != null) {
|
||||||
if (cacheResult != null) {
|
cachedResult = checkCache(uow, facets);
|
||||||
result = Optional.of(cacheResult);
|
if (cachedResult != null) {
|
||||||
updateCache = false;
|
updateCache = false;
|
||||||
} else {
|
result = Optional.of(cachedResult);
|
||||||
if (isSessionCacheable()) {
|
uowCacheHits.mark();
|
||||||
String tableName = CacheUtil.schemaName(facets);
|
cacheHits.mark();
|
||||||
cacheResult = (E) sessionOps.checkCache(tableName, facets);
|
uow.recordCacheAndDatabaseOperationCount(1, 0);
|
||||||
if (cacheResult != null) {
|
} else {
|
||||||
result = Optional.of(cacheResult);
|
updateCache = true;
|
||||||
|
uowCacheMiss.mark();
|
||||||
|
if (isSessionCacheable()) {
|
||||||
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
|
cachedResult = (E) sessionOps.checkCache(tableName, facets);
|
||||||
|
if (cachedResult != null) {
|
||||||
|
result = Optional.of(cachedResult);
|
||||||
|
sessionCacheHits.mark();
|
||||||
|
cacheHits.mark();
|
||||||
|
uow.recordCacheAndDatabaseOperationCount(1, 0);
|
||||||
|
} else {
|
||||||
|
sessionCacheMiss.mark();
|
||||||
|
cacheMiss.mark();
|
||||||
|
uow.recordCacheAndDatabaseOperationCount(-1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
updateCache = false;
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
timer.stop();
|
||||||
|
uow.addCacheLookupTime(timer);
|
||||||
}
|
}
|
||||||
timer.stop();
|
} else {
|
||||||
|
updateCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.isPresent()) {
|
// Check to see if we fetched the object from the cache
|
||||||
|
if (result.isPresent()) {
|
||||||
|
// If we fetched the `deleted` object then the result is null (really
|
||||||
|
// Optional.empty()).
|
||||||
|
if (result.get() == deleted) {
|
||||||
|
result = Optional.empty();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
// Formulate the query and execute it against the Cassandra cluster.
|
// Formulate the query and execute it against the Cassandra cluster.
|
||||||
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
||||||
showValues, true);
|
showValues, true);
|
||||||
|
@ -136,10 +174,9 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a result, it wasn't from the UOW cache, and we're caching things
|
// If we have a result, it wasn't from the UOW cache, and we're caching things
|
||||||
// then we
|
// then we need to put this result into the cache for future requests to find.
|
||||||
// need to put this result into the cache for future requests to find.
|
if (updateCache && result.isPresent() && result.get() != deleted) {
|
||||||
if (updateCache && result.isPresent()) {
|
cacheUpdate(uow, result.get(), getFacets());
|
||||||
updateCache(uow, result.get(), getFacets());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -150,11 +187,11 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
|
|
||||||
public CompletableFuture<Optional<E>> async() {
|
public CompletableFuture<Optional<E>> async() {
|
||||||
return CompletableFuture.<Optional<E>>supplyAsync(() -> {
|
return CompletableFuture.<Optional<E>>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +199,11 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return async();
|
return async();
|
||||||
return CompletableFuture.<Optional<E>>supplyAsync(() -> {
|
return CompletableFuture.<Optional<E>>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,6 @@ import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.ConsistencyLevel;
|
import com.datastax.driver.core.ConsistencyLevel;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
import com.datastax.driver.core.RegularStatement;
|
import com.datastax.driver.core.RegularStatement;
|
||||||
|
@ -42,14 +39,13 @@ import net.helenus.core.UnitOfWork;
|
||||||
import net.helenus.core.cache.Facet;
|
import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.cache.UnboundFacet;
|
import net.helenus.core.cache.UnboundFacet;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.value.BeanColumnValueProvider;
|
import net.helenus.mapping.value.BeanColumnValueProvider;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> extends Operation<E> {
|
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> extends Operation<E> {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractStatementOperation.class);
|
protected boolean checkCache = true;
|
||||||
|
|
||||||
protected boolean enableCache = true;
|
|
||||||
protected boolean showValues = true;
|
protected boolean showValues = true;
|
||||||
protected TraceContext traceContext;
|
protected TraceContext traceContext;
|
||||||
long queryExecutionTimeout = 10;
|
long queryExecutionTimeout = 10;
|
||||||
|
@ -70,13 +66,13 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
|
|
||||||
public abstract Statement buildStatement(boolean cached);
|
public abstract Statement buildStatement(boolean cached);
|
||||||
|
|
||||||
public O ignoreCache(boolean enabled) {
|
public O uncached(boolean enabled) {
|
||||||
enableCache = enabled;
|
checkCache = enabled;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O ignoreCache() {
|
public O uncached() {
|
||||||
enableCache = true;
|
checkCache = false;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,21 +322,14 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
if (!facets.isEmpty()) {
|
if (!facets.isEmpty()) {
|
||||||
optionalCachedResult = uow.cacheLookup(facets);
|
optionalCachedResult = uow.cacheLookup(facets);
|
||||||
if (optionalCachedResult.isPresent()) {
|
if (optionalCachedResult.isPresent()) {
|
||||||
uowCacheHits.mark();
|
|
||||||
LOG.info("UnitOfWork({}) cache hit using facets", uow.hashCode());
|
|
||||||
result = (E) optionalCachedResult.get();
|
result = (E) optionalCachedResult.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
uowCacheMiss.mark();
|
|
||||||
LOG.info("UnitOfWork({}) cache miss", uow.hashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateCache(UnitOfWork<?> uow, E pojo, List<Facet> identifyingFacets) {
|
protected void cacheUpdate(UnitOfWork<?> uow, E pojo, List<Facet> identifyingFacets) {
|
||||||
List<Facet> facets = new ArrayList<>();
|
List<Facet> facets = new ArrayList<>();
|
||||||
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
Map<String, Object> valueMap = pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null;
|
||||||
|
|
||||||
|
@ -348,15 +337,23 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
if (facet instanceof UnboundFacet) {
|
if (facet instanceof UnboundFacet) {
|
||||||
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
||||||
UnboundFacet.Binder binder = unboundFacet.binder();
|
UnboundFacet.Binder binder = unboundFacet.binder();
|
||||||
unboundFacet.getProperties().forEach(prop -> {
|
for (HelenusProperty prop : unboundFacet.getProperties()) {
|
||||||
|
Object value;
|
||||||
if (valueMap == null) {
|
if (valueMap == null) {
|
||||||
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
|
value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop, false);
|
||||||
binder.setValueForProperty(prop, value.toString());
|
if (value != null) {
|
||||||
|
binder.setValueForProperty(prop, value.toString());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
binder.setValueForProperty(prop, valueMap.get(prop.getPropertyName()).toString());
|
value = valueMap.get(prop.getPropertyName());
|
||||||
|
if (value != null) {
|
||||||
|
binder.setValueForProperty(prop, value.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (binder.isBound()) {
|
||||||
facets.add(binder.bind());
|
facets.add(binder.bind());
|
||||||
});
|
}
|
||||||
} else {
|
} else {
|
||||||
facets.add(facet);
|
facets.add(facet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import static net.helenus.core.HelenusSession.deleted;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
|
@ -58,20 +62,25 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<E> sync() {// throws TimeoutException {
|
public Stream<E> sync() throws TimeoutException {
|
||||||
final Timer.Context context = requestLatency.time();
|
final Timer.Context context = requestLatency.time();
|
||||||
try {
|
try {
|
||||||
Stream<E> resultStream = null;
|
Stream<E> resultStream = null;
|
||||||
E cacheResult = null;
|
E cacheResult = null;
|
||||||
boolean updateCache = isSessionCacheable();
|
boolean updateCache = isSessionCacheable();
|
||||||
|
|
||||||
if (enableCache && isSessionCacheable()) {
|
if (checkCache && isSessionCacheable()) {
|
||||||
List<Facet> facets = bindFacetValues();
|
List<Facet> facets = bindFacetValues();
|
||||||
String tableName = CacheUtil.schemaName(facets);
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
cacheResult = (E) sessionOps.checkCache(tableName, facets);
|
cacheResult = (E) sessionOps.checkCache(tableName, facets);
|
||||||
if (cacheResult != null) {
|
if (cacheResult != null) {
|
||||||
resultStream = Stream.of(cacheResult);
|
resultStream = Stream.of(cacheResult);
|
||||||
updateCache = false;
|
updateCache = false;
|
||||||
|
sessionCacheHits.mark();
|
||||||
|
cacheHits.mark();
|
||||||
|
} else {
|
||||||
|
sessionCacheMiss.mark();
|
||||||
|
cacheMiss.mark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +111,7 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<E> sync(UnitOfWork<?> uow) {// throws TimeoutException {
|
public Stream<E> sync(UnitOfWork uow) throws TimeoutException {
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return sync();
|
return sync();
|
||||||
|
|
||||||
|
@ -110,20 +119,50 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
try {
|
try {
|
||||||
Stream<E> resultStream = null;
|
Stream<E> resultStream = null;
|
||||||
E cachedResult = null;
|
E cachedResult = null;
|
||||||
boolean updateCache = true;
|
final boolean updateCache;
|
||||||
|
|
||||||
if (enableCache) {
|
if (checkCache) {
|
||||||
Stopwatch timer = uow.getCacheLookupTimer();
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
timer.start();
|
try {
|
||||||
List<Facet> facets = bindFacetValues();
|
List<Facet> facets = bindFacetValues();
|
||||||
cachedResult = checkCache(uow, facets);
|
if (facets != null) {
|
||||||
if (cachedResult != null) {
|
cachedResult = checkCache(uow, facets);
|
||||||
resultStream = Stream.of(cachedResult);
|
if (cachedResult != null) {
|
||||||
updateCache = false;
|
updateCache = false;
|
||||||
|
resultStream = Stream.of(cachedResult);
|
||||||
|
uowCacheHits.mark();
|
||||||
|
cacheHits.mark();
|
||||||
|
uow.recordCacheAndDatabaseOperationCount(1, 0);
|
||||||
|
} else {
|
||||||
|
updateCache = true;
|
||||||
|
uowCacheMiss.mark();
|
||||||
|
if (isSessionCacheable()) {
|
||||||
|
String tableName = CacheUtil.schemaName(facets);
|
||||||
|
cachedResult = (E) sessionOps.checkCache(tableName, facets);
|
||||||
|
if (cachedResult != null) {
|
||||||
|
resultStream = Stream.of(cachedResult);
|
||||||
|
sessionCacheHits.mark();
|
||||||
|
cacheHits.mark();
|
||||||
|
uow.recordCacheAndDatabaseOperationCount(1, 0);
|
||||||
|
} else {
|
||||||
|
sessionCacheMiss.mark();
|
||||||
|
cacheMiss.mark();
|
||||||
|
uow.recordCacheAndDatabaseOperationCount(-1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateCache = false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
timer.stop();
|
||||||
|
uow.addCacheLookupTime(timer);
|
||||||
}
|
}
|
||||||
timer.stop();
|
} else {
|
||||||
|
updateCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to see if we fetched the object from the cache
|
||||||
if (resultStream == null) {
|
if (resultStream == null) {
|
||||||
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
ResultSet resultSet = execute(sessionOps, uow, traceContext, queryExecutionTimeout, queryTimeoutUnits,
|
||||||
showValues, true);
|
showValues, true);
|
||||||
|
@ -132,12 +171,16 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
|
|
||||||
// If we have a result and we're caching then we need to put it into the cache
|
// If we have a result and we're caching then we need to put it into the cache
|
||||||
// for future requests to find.
|
// for future requests to find.
|
||||||
if (updateCache && resultStream != null) {
|
if (resultStream != null) {
|
||||||
List<E> again = new ArrayList<>();
|
List<E> again = new ArrayList<>();
|
||||||
List<Facet> facets = getFacets();
|
List<Facet> facets = getFacets();
|
||||||
resultStream.forEach(result -> {
|
resultStream.forEach(result -> {
|
||||||
updateCache(uow, result, facets);
|
if (result != deleted) {
|
||||||
again.add(result);
|
if (updateCache) {
|
||||||
|
cacheUpdate(uow, result, facets);
|
||||||
|
}
|
||||||
|
again.add(result);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
resultStream = again.stream();
|
resultStream = again.stream();
|
||||||
}
|
}
|
||||||
|
@ -150,23 +193,23 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
|
|
||||||
public CompletableFuture<Stream<E>> async() {
|
public CompletableFuture<Stream<E>> async() {
|
||||||
return CompletableFuture.<Stream<E>>supplyAsync(() -> {
|
return CompletableFuture.<Stream<E>>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Stream<E>> async(UnitOfWork<?> uow) {
|
public CompletableFuture<Stream<E>> async(UnitOfWork uow) {
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
return async();
|
return async();
|
||||||
return CompletableFuture.<Stream<E>>supplyAsync(() -> {
|
return CompletableFuture.<Stream<E>>supplyAsync(() -> {
|
||||||
// try {
|
try {
|
||||||
return sync();
|
return sync();
|
||||||
// } catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
// throw new CompletionException(ex);
|
throw new CompletionException(ex);
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import com.datastax.driver.core.querybuilder.Delete;
|
import com.datastax.driver.core.querybuilder.Delete;
|
||||||
|
@ -23,6 +26,8 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Filter;
|
import net.helenus.core.Filter;
|
||||||
|
import net.helenus.core.UnitOfWork;
|
||||||
|
import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
@ -122,4 +127,33 @@ public final class DeleteOperation extends AbstractFilterOperation<ResultSet, De
|
||||||
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
|
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Facet> bindFacetValues() {
|
||||||
|
return bindFacetValues(getFacets());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultSet sync() throws TimeoutException {
|
||||||
|
ResultSet result = super.sync();
|
||||||
|
if (entity.isCacheable()) {
|
||||||
|
sessionOps.cacheEvict(bindFacetValues());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultSet sync(UnitOfWork uow) throws TimeoutException {
|
||||||
|
if (uow == null) {
|
||||||
|
return sync();
|
||||||
|
}
|
||||||
|
ResultSet result = super.sync(uow);
|
||||||
|
uow.cacheEvict(bindFacetValues());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Facet> getFacets() {
|
||||||
|
return entity.getFacets();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
@ -27,6 +28,7 @@ import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Getter;
|
import net.helenus.core.Getter;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
|
import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
||||||
import net.helenus.core.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
@ -235,15 +237,38 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T sync(UnitOfWork uow) {// throws TimeoutException {
|
public T sync() throws TimeoutException {
|
||||||
|
T result = super.sync();
|
||||||
|
if (entity.isCacheable() && result != null) {
|
||||||
|
sessionOps.updateCache(result, entity.getFacets());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T sync(UnitOfWork uow) throws TimeoutException {
|
||||||
if (uow == null) {
|
if (uow == null) {
|
||||||
return sync();
|
return sync();
|
||||||
}
|
}
|
||||||
T result = super.sync(uow);
|
T result = super.sync(uow);
|
||||||
Class<?> iface = entity.getMappingInterface();
|
Class<?> iface = entity.getMappingInterface();
|
||||||
if (resultType == iface) {
|
if (resultType == iface) {
|
||||||
updateCache(uow, result, entity.getFacets());
|
cacheUpdate(uow, result, entity.getFacets());
|
||||||
|
} else {
|
||||||
|
if (entity.isCacheable()) {
|
||||||
|
sessionOps.cacheEvict(bindFacetValues());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Facet> getFacets() {
|
||||||
|
if (entity != null) {
|
||||||
|
return entity.getFacets();
|
||||||
|
} else {
|
||||||
|
return new ArrayList<Facet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
|
import com.datastax.driver.core.RegularStatement;
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.ResultSetFuture;
|
import com.datastax.driver.core.ResultSetFuture;
|
||||||
import com.datastax.driver.core.Statement;
|
import com.datastax.driver.core.Statement;
|
||||||
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import com.google.common.base.Stopwatch;
|
import com.google.common.base.Stopwatch;
|
||||||
|
|
||||||
import brave.Span;
|
import brave.Span;
|
||||||
|
@ -35,21 +42,54 @@ import net.helenus.core.cache.Facet;
|
||||||
|
|
||||||
public abstract class Operation<E> {
|
public abstract class Operation<E> {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(Operation.class);
|
||||||
|
|
||||||
protected final AbstractSessionOperations sessionOps;
|
protected final AbstractSessionOperations sessionOps;
|
||||||
protected final Meter uowCacheHits;
|
protected final Meter uowCacheHits;
|
||||||
protected final Meter uowCacheMiss;
|
protected final Meter uowCacheMiss;
|
||||||
|
protected final Meter sessionCacheHits;
|
||||||
|
protected final Meter sessionCacheMiss;
|
||||||
|
protected final Meter cacheHits;
|
||||||
|
protected final Meter cacheMiss;
|
||||||
protected final Timer requestLatency;
|
protected final Timer requestLatency;
|
||||||
|
|
||||||
Operation(AbstractSessionOperations sessionOperations) {
|
Operation(AbstractSessionOperations sessionOperations) {
|
||||||
this.sessionOps = sessionOperations;
|
this.sessionOps = sessionOperations;
|
||||||
MetricRegistry metrics = sessionOperations.getMetricRegistry();
|
MetricRegistry metrics = sessionOperations.getMetricRegistry();
|
||||||
|
if (metrics == null) {
|
||||||
|
metrics = new MetricRegistry();
|
||||||
|
}
|
||||||
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
|
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
|
||||||
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
|
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
|
||||||
|
this.sessionCacheHits = metrics.meter("net.helenus.session-cache-hits");
|
||||||
|
this.sessionCacheMiss = metrics.meter("net.helenus.session-cache-miss");
|
||||||
|
this.cacheHits = metrics.meter("net.helenus.cache-hits");
|
||||||
|
this.cacheMiss = metrics.meter("net.helenus.cache-miss");
|
||||||
this.requestLatency = metrics.timer("net.helenus.request-latency");
|
this.requestLatency = metrics.timer("net.helenus.request-latency");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String queryString(Statement statement, boolean includeValues) {
|
||||||
|
String query = null;
|
||||||
|
if (statement instanceof BuiltStatement) {
|
||||||
|
BuiltStatement builtStatement = (BuiltStatement) statement;
|
||||||
|
if (includeValues) {
|
||||||
|
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
|
||||||
|
query = regularStatement.getQueryString();
|
||||||
|
} else {
|
||||||
|
query = builtStatement.getQueryString();
|
||||||
|
}
|
||||||
|
} else if (statement instanceof RegularStatement) {
|
||||||
|
RegularStatement regularStatement = (RegularStatement) statement;
|
||||||
|
query = regularStatement.getQueryString();
|
||||||
|
} else {
|
||||||
|
query = statement.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, long timeout,
|
public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, long timeout,
|
||||||
TimeUnit units, boolean showValues, boolean cached) { // throws TimeoutException {
|
TimeUnit units, boolean showValues, boolean cached) throws TimeoutException {
|
||||||
|
|
||||||
// Start recording in a Zipkin sub-span our execution time to perform this
|
// Start recording in a Zipkin sub-span our execution time to perform this
|
||||||
// operation.
|
// operation.
|
||||||
|
@ -67,18 +107,20 @@ public abstract class Operation<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement statement = options(buildStatement(cached));
|
Statement statement = options(buildStatement(cached));
|
||||||
Stopwatch timer = null;
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
if (uow != null) {
|
try {
|
||||||
timer = uow.getExecutionTimer();
|
ResultSetFuture futureResultSet = session.executeAsync(statement, uow, timer, showValues);
|
||||||
timer.start();
|
if (uow != null)
|
||||||
}
|
uow.recordCacheAndDatabaseOperationCount(0, 1);
|
||||||
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
ResultSet resultSet = futureResultSet.getUninterruptibly(timeout, units);
|
||||||
ResultSet resultSet = futureResultSet.getUninterruptibly(); // TODO(gburd): (timeout, units);
|
return resultSet;
|
||||||
|
|
||||||
if (uow != null)
|
} finally {
|
||||||
timer.stop();
|
timer.stop();
|
||||||
|
if (uow != null)
|
||||||
return resultSet;
|
uow.addDatabaseTime("Cassandra", timer);
|
||||||
|
log(statement, uow, timer, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
||||||
|
@ -88,6 +130,20 @@ public abstract class Operation<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log(Statement statement, UnitOfWork uow, Stopwatch timer, boolean showValues) {
|
||||||
|
if (LOG.isInfoEnabled()) {
|
||||||
|
String uowString = "";
|
||||||
|
if (uow != null) {
|
||||||
|
uowString = "UOW(" + uow.hashCode() + ")";
|
||||||
|
}
|
||||||
|
String timerString = "";
|
||||||
|
if (timer != null) {
|
||||||
|
timerString = String.format(" %s ", timer.toString());
|
||||||
|
}
|
||||||
|
LOG.info(String.format("%s%s%s", uowString, timerString, Operation.queryString(statement, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Statement options(Statement statement) {
|
public Statement options(Statement statement) {
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +153,7 @@ public abstract class Operation<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Facet> getFacets() {
|
public List<Facet> getFacets() {
|
||||||
return null;
|
return new ArrayList<Facet>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Facet> bindFacetValues() {
|
public List<Facet> bindFacetValues() {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.cache.UnboundFacet;
|
import net.helenus.core.cache.UnboundFacet;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
import net.helenus.mapping.OrderingDirection;
|
import net.helenus.mapping.OrderingDirection;
|
||||||
import net.helenus.mapping.value.ColumnValueProvider;
|
import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
|
@ -206,16 +207,18 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
if (facet instanceof UnboundFacet) {
|
if (facet instanceof UnboundFacet) {
|
||||||
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
UnboundFacet unboundFacet = (UnboundFacet) facet;
|
||||||
UnboundFacet.Binder binder = unboundFacet.binder();
|
UnboundFacet.Binder binder = unboundFacet.binder();
|
||||||
unboundFacet.getProperties().forEach(prop -> {
|
for (HelenusProperty prop : unboundFacet.getProperties()) {
|
||||||
Filter filter = filters.get(prop);
|
if (filters != null) {
|
||||||
if (filter != null) {
|
Filter filter = filters.get(prop);
|
||||||
Object[] postulates = filter.postulateValues();
|
if (filter != null) {
|
||||||
for (Object p : postulates) {
|
Object[] postulates = filter.postulateValues();
|
||||||
binder.setValueForProperty(prop, p.toString());
|
for (Object p : postulates) {
|
||||||
|
binder.setValueForProperty(prop, p.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
if (binder.isBound()) {
|
if (binder.isBound()) {
|
||||||
boundFacets.add(binder.bind());
|
boundFacets.add(binder.bind());
|
||||||
}
|
}
|
||||||
|
@ -247,7 +250,9 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
+ entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface());
|
+ entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached) {
|
// TODO(gburd): writeTime and ttl will be useful on merge() but cause object
|
||||||
|
// identity to fail.
|
||||||
|
if (false && cached) {
|
||||||
switch (prop.getProperty().getColumnType()) {
|
switch (prop.getProperty().getColumnType()) {
|
||||||
case PARTITION_KEY :
|
case PARTITION_KEY :
|
||||||
case CLUSTERING_COLUMN :
|
case CLUSTERING_COLUMN :
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.querybuilder.Assignment;
|
import com.datastax.driver.core.querybuilder.Assignment;
|
||||||
|
@ -25,19 +27,25 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
import com.datastax.driver.core.querybuilder.Update;
|
import com.datastax.driver.core.querybuilder.Update;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
import net.helenus.core.cache.BoundFacet;
|
||||||
|
import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
import net.helenus.core.reflect.MapExportable;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
|
import net.helenus.mapping.value.BeanColumnValueProvider;
|
||||||
|
import net.helenus.mapping.value.ValueProviderMap;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
import net.helenus.support.Immutables;
|
import net.helenus.support.Immutables;
|
||||||
|
|
||||||
public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateOperation<E>> {
|
public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateOperation<E>> {
|
||||||
|
|
||||||
private final List<Assignment> assignments = new ArrayList<Assignment>();
|
private final Map<Assignment, BoundFacet> assignments = new HashMap<>();
|
||||||
private final AbstractEntityDraft<E> draft;
|
private final AbstractEntityDraft<E> draft;
|
||||||
private final Map<String, Object> draftMap;
|
private final Map<String, Object> draftMap;
|
||||||
private HelenusEntity entity = null;
|
private HelenusEntity entity = null;
|
||||||
|
private Object pojo;
|
||||||
private int[] ttl;
|
private int[] ttl;
|
||||||
private long[] timestamp;
|
private long[] timestamp;
|
||||||
|
|
||||||
|
@ -53,13 +61,21 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
this.draftMap = draft.toMap();
|
this.draftMap = draft.toMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateOperation(AbstractSessionOperations sessionOperations, Object pojo) {
|
||||||
|
super(sessionOperations);
|
||||||
|
this.draft = null;
|
||||||
|
this.draftMap = null;
|
||||||
|
this.pojo = pojo;
|
||||||
|
this.entity = Helenus.resolve(MappingUtil.getMappingInterface(pojo));
|
||||||
|
}
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.draft = null;
|
this.draft = null;
|
||||||
this.draftMap = null;
|
this.draftMap = null;
|
||||||
|
|
||||||
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
||||||
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
assignments.put(QueryBuilder.set(p.getColumnName(), value), new BoundFacet(p.getProperty(), v));
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
}
|
}
|
||||||
|
@ -68,9 +84,29 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
Objects.requireNonNull(getter, "getter is empty");
|
Objects.requireNonNull(getter, "getter is empty");
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
HelenusProperty prop = p.getProperty();
|
||||||
|
|
||||||
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, prop);
|
||||||
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
assignments.put(QueryBuilder.set(p.getColumnName(), value), new BoundFacet(prop, value));
|
||||||
|
|
||||||
|
if (draft != null) {
|
||||||
|
String key = prop.getPropertyName();
|
||||||
|
if (draft.get(key, value.getClass()) != value) {
|
||||||
|
draft.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
|
if (entity.isCacheable() && pojo != null && pojo instanceof MapExportable) {
|
||||||
|
String key = prop.getPropertyName();
|
||||||
|
Map<String, Object> map = ((MapExportable) pojo).toMap();
|
||||||
|
if (!(map instanceof ValueProviderMap)) {
|
||||||
|
if (map.get(key) != value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
|
|
||||||
|
@ -95,15 +131,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.incr(p.getColumnName(), delta));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Long value = (Long) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
|
||||||
if (draft != null) {
|
facet = new BoundFacet(prop, value + delta);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
draftMap.put(key, (Long) draftMap.get(key) + delta);
|
draftMap.put(key, (Long) draftMap.get(key) + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignments.put(QueryBuilder.incr(p.getColumnName(), delta), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,15 +158,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.decr(p.getColumnName(), delta));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Long value = (Long) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
|
||||||
if (draft != null) {
|
facet = new BoundFacet(prop, value - delta);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
draftMap.put(key, (Long) draftMap.get(key) - delta);
|
draftMap.put(key, (Long) draftMap.get(key) - delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignments.put(QueryBuilder.decr(p.getColumnName(), delta), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,16 +190,22 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.prepend(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
list.add(0, value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.add(0, value);
|
list.add(0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignments.put(QueryBuilder.prepend(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,16 +217,22 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
List valueObj = prepareListValue(p, value);
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.prependAll(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null && value.size() > 0) {
|
list.addAll(0, value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null && value.size() > 0) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.addAll(0, value);
|
list.addAll(0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignments.put(QueryBuilder.prependAll(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +244,16 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null || draft != null) {
|
||||||
addPropertyNode(p);
|
List<V> list;
|
||||||
|
HelenusProperty prop = p.getProperty();
|
||||||
if (draft != null) {
|
if (pojo != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
} else {
|
||||||
|
String key = p.getProperty().getPropertyName();
|
||||||
|
list = (List<V>) draftMap.get(key);
|
||||||
|
}
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
list.add(0, value);
|
list.add(0, value);
|
||||||
} else if (idx > list.size()) {
|
} else if (idx > list.size()) {
|
||||||
|
@ -201,8 +262,13 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
list.add(idx, value);
|
list.add(idx, value);
|
||||||
}
|
}
|
||||||
list.add(0, value);
|
list.add(0, value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignments.put(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,15 +280,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.append(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
list.add(value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.add(value);
|
list.add(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.append(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -235,15 +306,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
List valueObj = prepareListValue(p, value);
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.appendAll(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null && value.size() > 0) {
|
list.addAll(value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null && value.size() > 0) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.addAll(value);
|
list.addAll(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.appendAll(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -256,15 +332,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.discard(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
list.remove(value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.remove(value);
|
list.remove(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.discard(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -277,15 +358,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
List valueObj = prepareListValue(p, value);
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.discardAll(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
List<V> list = new ArrayList<V>((List<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
list.removeAll(value);
|
||||||
|
facet = new BoundFacet(prop, list);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>) draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.removeAll(value);
|
list.removeAll(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.discardAll(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -334,15 +420,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
Object valueObj = prepareSingleSetValue(p, value);
|
Object valueObj = prepareSingleSetValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.add(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
set.add(value);
|
||||||
|
facet = new BoundFacet(prop, set);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
Set<V> set = (Set<V>) draftMap.get(key);
|
Set<V> set = (Set<V>) draftMap.get(key);
|
||||||
set.add(value);
|
set.add(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.add(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -355,15 +446,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
Set valueObj = prepareSetValue(p, value);
|
Set valueObj = prepareSetValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.addAll(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
set.addAll(value);
|
||||||
|
facet = new BoundFacet(prop, set);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
Set<V> set = (Set<V>) draftMap.get(key);
|
Set<V> set = (Set<V>) draftMap.get(key);
|
||||||
set.addAll(value);
|
set.addAll(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.addAll(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -376,15 +472,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
Object valueObj = prepareSingleSetValue(p, value);
|
Object valueObj = prepareSingleSetValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.remove(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
set.remove(value);
|
||||||
|
facet = new BoundFacet(prop, set);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
Set<V> set = (Set<V>) draftMap.get(key);
|
Set<V> set = (Set<V>) draftMap.get(key);
|
||||||
set.remove(value);
|
set.remove(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.remove(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -397,15 +498,20 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
Set valueObj = prepareSetValue(p, value);
|
Set valueObj = prepareSetValue(p, value);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.removeAll(p.getColumnName(), valueObj));
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
|
Set<V> set = new HashSet<V>((Set<V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
if (draft != null) {
|
set.removeAll(value);
|
||||||
|
facet = new BoundFacet(prop, set);
|
||||||
|
} else if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
Set<V> set = (Set<V>) draftMap.get(key);
|
Set<V> set = (Set<V>) draftMap.get(key);
|
||||||
set.removeAll(value);
|
set.removeAll(value);
|
||||||
}
|
}
|
||||||
|
assignments.put(QueryBuilder.removeAll(p.getColumnName(), valueObj), facet);
|
||||||
|
|
||||||
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -453,23 +559,29 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
||||||
HelenusProperty prop = p.getProperty();
|
HelenusProperty prop = p.getProperty();
|
||||||
|
|
||||||
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
|
Map<K, V> map = new HashMap<K, V>(
|
||||||
|
(Map<K, V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
|
map.put(key, value);
|
||||||
|
facet = new BoundFacet(prop, map);
|
||||||
|
} else if (draft != null) {
|
||||||
|
((Map<K, V>) draftMap.get(prop.getPropertyName())).put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
if (converter.isPresent()) {
|
if (converter.isPresent()) {
|
||||||
Map<Object, Object> convertedMap = (Map<Object, Object>) converter.get()
|
Map<Object, Object> convertedMap = (Map<Object, Object>) converter.get()
|
||||||
.apply(Immutables.mapOf(key, value));
|
.apply(Immutables.mapOf(key, value));
|
||||||
for (Map.Entry<Object, Object> e : convertedMap.entrySet()) {
|
for (Map.Entry<Object, Object> e : convertedMap.entrySet()) {
|
||||||
assignments.add(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue()));
|
assignments.put(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue()), facet);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assignments.add(QueryBuilder.put(p.getColumnName(), key, value));
|
assignments.put(QueryBuilder.put(p.getColumnName(), key, value), facet);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
|
|
||||||
if (draft != null) {
|
|
||||||
((Map<K, V>) draftMap.get(prop.getPropertyName())).put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,20 +593,26 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
||||||
HelenusProperty prop = p.getProperty();
|
HelenusProperty prop = p.getProperty();
|
||||||
|
|
||||||
|
BoundFacet facet = null;
|
||||||
|
if (pojo != null) {
|
||||||
|
Map<K, V> newMap = new HashMap<K, V>(
|
||||||
|
(Map<K, V>) BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
|
newMap.putAll(map);
|
||||||
|
facet = new BoundFacet(prop, newMap);
|
||||||
|
} else if (draft != null) {
|
||||||
|
((Map<K, V>) draftMap.get(prop.getPropertyName())).putAll(map);
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
if (converter.isPresent()) {
|
if (converter.isPresent()) {
|
||||||
Map convertedMap = (Map) converter.get().apply(map);
|
Map convertedMap = (Map) converter.get().apply(map);
|
||||||
assignments.add(QueryBuilder.putAll(p.getColumnName(), convertedMap));
|
assignments.put(QueryBuilder.putAll(p.getColumnName(), convertedMap), facet);
|
||||||
} else {
|
} else {
|
||||||
assignments.add(QueryBuilder.putAll(p.getColumnName(), map));
|
assignments.put(QueryBuilder.putAll(p.getColumnName(), map), facet);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
|
|
||||||
if (draft != null) {
|
|
||||||
((Map<K, V>) draftMap.get(prop.getPropertyName())).putAll(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +625,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
Update update = QueryBuilder.update(entity.getName().toCql());
|
Update update = QueryBuilder.update(entity.getName().toCql());
|
||||||
|
|
||||||
for (Assignment assignment : assignments) {
|
for (Assignment assignment : assignments.keySet()) {
|
||||||
update.with(assignment);
|
update.with(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,16 +685,48 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E sync(UnitOfWork uow) {// throws TimeoutException {
|
public E sync() throws TimeoutException {
|
||||||
|
E result = super.sync();
|
||||||
|
if (entity.isCacheable()) {
|
||||||
|
if (draft != null) {
|
||||||
|
sessionOps.updateCache(draft, bindFacetValues());
|
||||||
|
} else if (pojo != null) {
|
||||||
|
sessionOps.updateCache(pojo, bindFacetValues());
|
||||||
|
} else {
|
||||||
|
sessionOps.cacheEvict(bindFacetValues());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E sync(UnitOfWork uow) throws TimeoutException {
|
||||||
if (uow == null) {
|
if (uow == null) {
|
||||||
return sync();
|
return sync();
|
||||||
}
|
}
|
||||||
E result = super.sync(uow);
|
E result = super.sync(uow);
|
||||||
// TODO(gburd): Only drafted entity objects are updated in the cache at this
|
|
||||||
// time.
|
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
updateCache(uow, result, getFacets());
|
cacheUpdate(uow, result, bindFacetValues());
|
||||||
|
} else if (pojo != null) {
|
||||||
|
cacheUpdate(uow, (E) pojo, bindFacetValues());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Facet> bindFacetValues() {
|
||||||
|
List<Facet> facets = bindFacetValues(entity.getFacets());
|
||||||
|
facets.addAll(assignments.values().stream().distinct().filter(o -> o != null).collect(Collectors.toList()));
|
||||||
|
return facets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Facet> getFacets() {
|
||||||
|
if (entity != null) {
|
||||||
|
return entity.getFacets();
|
||||||
|
} else {
|
||||||
|
return new ArrayList<Facet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package net.helenus.core.reflect;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -63,31 +64,33 @@ public class DslInvocationHandler<E> implements InvocationHandler {
|
||||||
|
|
||||||
private HelenusEntity init(Metadata metadata) {
|
private HelenusEntity init(Metadata metadata) {
|
||||||
HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
|
HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
|
||||||
|
Collection<HelenusProperty> properties = entity.getOrderedProperties();
|
||||||
|
if (properties != null) {
|
||||||
|
for (HelenusProperty prop : properties) {
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
map.put(prop.getGetterMethod(), prop);
|
||||||
|
|
||||||
map.put(prop.getGetterMethod(), prop);
|
AbstractDataType type = prop.getDataType();
|
||||||
|
Class<?> javaType = prop.getJavaType();
|
||||||
|
|
||||||
AbstractDataType type = prop.getDataType();
|
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
|
||||||
Class<?> javaType = prop.getJavaType();
|
|
||||||
|
|
||||||
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
|
|
||||||
|
|
||||||
Object childDsl = Helenus.dsl(javaType, classLoader, Optional.of(new HelenusPropertyNode(prop, parent)),
|
|
||||||
metadata);
|
|
||||||
|
|
||||||
udtMap.put(prop.getGetterMethod(), childDsl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type instanceof DTDataType) {
|
|
||||||
DTDataType dataType = (DTDataType) type;
|
|
||||||
|
|
||||||
if (dataType.getDataType() instanceof TupleType && !TupleValue.class.isAssignableFrom(javaType)) {
|
|
||||||
|
|
||||||
Object childDsl = Helenus.dsl(javaType, classLoader,
|
Object childDsl = Helenus.dsl(javaType, classLoader,
|
||||||
Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
|
Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
|
||||||
|
|
||||||
tupleMap.put(prop.getGetterMethod(), childDsl);
|
udtMap.put(prop.getGetterMethod(), childDsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type instanceof DTDataType) {
|
||||||
|
DTDataType dataType = (DTDataType) type;
|
||||||
|
|
||||||
|
if (dataType.getDataType() instanceof TupleType && !TupleValue.class.isAssignableFrom(javaType)) {
|
||||||
|
|
||||||
|
Object childDsl = Helenus.dsl(javaType, classLoader,
|
||||||
|
Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
|
||||||
|
|
||||||
|
tupleMap.put(prop.getGetterMethod(), childDsl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
|
import java.io.InvalidObjectException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectStreamException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Collections;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.mapping.annotation.Transient;
|
import net.helenus.mapping.annotation.Transient;
|
||||||
|
import net.helenus.mapping.value.ValueProviderMap;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public class MapperInvocationHandler<E> implements InvocationHandler, Serializable {
|
public class MapperInvocationHandler<E> implements InvocationHandler, Serializable {
|
||||||
|
@ -59,6 +64,13 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object writeReplace() {
|
||||||
|
return new SerializationProxy<E>(this);
|
||||||
|
}
|
||||||
|
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
|
||||||
|
throw new InvalidObjectException("Proxy required.");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
|
||||||
|
@ -97,12 +109,20 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
|
||||||
return iface.getSimpleName() + ": " + src.toString();
|
return iface.getSimpleName() + ": " + src.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("writeReplace".equals(methodName)) {
|
||||||
|
return new SerializationProxy(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("readObject".equals(methodName)) {
|
||||||
|
throw new InvalidObjectException("Proxy required.");
|
||||||
|
}
|
||||||
|
|
||||||
if ("dsl".equals(methodName)) {
|
if ("dsl".equals(methodName)) {
|
||||||
return Helenus.dsl(iface);
|
return Helenus.dsl(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
||||||
return Collections.unmodifiableMap(src);
|
return src; // return Collections.unmodifiableMap(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object value = src.get(methodName);
|
Object value = src.get(methodName);
|
||||||
|
@ -132,4 +152,30 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class SerializationProxy<E> implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5617583940055969353L;
|
||||||
|
|
||||||
|
private final Class<E> iface;
|
||||||
|
private final Map<String, Object> src;
|
||||||
|
|
||||||
|
public SerializationProxy(MapperInvocationHandler mapper) {
|
||||||
|
this.iface = mapper.iface;
|
||||||
|
if (mapper.src instanceof ValueProviderMap) {
|
||||||
|
this.src = new HashMap<String, Object>(mapper.src.size());
|
||||||
|
Set<String> keys = mapper.src.keySet();
|
||||||
|
for (String key : keys) {
|
||||||
|
this.src.put(key, mapper.src.get(key));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.src = mapper.src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object readResolve() throws ObjectStreamException {
|
||||||
|
return new MapperInvocationHandler(iface, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -28,7 +29,8 @@ public enum ReflectionMapperInstantiator implements MapperInstantiator {
|
||||||
public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
||||||
|
|
||||||
MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src);
|
MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src);
|
||||||
E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, MapExportable.class}, handler);
|
E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, MapExportable.class, Serializable.class},
|
||||||
|
handler);
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ package net.helenus.mapping;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ClassUtils;
|
import org.apache.commons.lang3.ClassUtils;
|
||||||
|
|
||||||
import com.datastax.driver.core.DefaultMetadata;
|
import com.datastax.driver.core.DefaultMetadata;
|
||||||
|
@ -31,6 +33,7 @@ import net.helenus.core.annotation.Cacheable;
|
||||||
import net.helenus.core.cache.Facet;
|
import net.helenus.core.cache.Facet;
|
||||||
import net.helenus.core.cache.UnboundFacet;
|
import net.helenus.core.cache.UnboundFacet;
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.*;
|
||||||
|
import net.helenus.mapping.validator.DistinctValidator;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class HelenusMappingEntity implements HelenusEntity {
|
public final class HelenusMappingEntity implements HelenusEntity {
|
||||||
|
@ -125,10 +128,12 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
||||||
facetsBuilder.add(new UnboundFacet(primaryKeyProperties));
|
facetsBuilder.add(new UnboundFacet(primaryKeyProperties));
|
||||||
primaryKeyProperties = null;
|
primaryKeyProperties = null;
|
||||||
}
|
}
|
||||||
Optional<IdentityName> optionalIndexName = prop.getIndexName();
|
for (ConstraintValidator<?, ?> constraint : MappingUtil.getValidators(prop.getGetterMethod())) {
|
||||||
if (optionalIndexName.isPresent()) {
|
if (constraint.getClass().isAssignableFrom(DistinctValidator.class)) {
|
||||||
UnboundFacet facet = new UnboundFacet(prop);
|
UnboundFacet facet = new UnboundFacet(prop);
|
||||||
facetsBuilder.add(facet);
|
facetsBuilder.add(facet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -282,4 +283,41 @@ public final class MappingUtil {
|
||||||
return e.getPropertyNode();
|
return e.getPropertyNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/4882306/366692
|
||||||
|
public static <T> T clone(T object) throws CloneNotSupportedException {
|
||||||
|
Object clone = null;
|
||||||
|
|
||||||
|
// Use reflection, because there is no other way
|
||||||
|
try {
|
||||||
|
Method method = object.getClass().getMethod("clone");
|
||||||
|
clone = method.invoke(object);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
rethrow(e.getCause());
|
||||||
|
} catch (Exception cause) {
|
||||||
|
rethrow(cause);
|
||||||
|
}
|
||||||
|
if (object.getClass().isInstance(clone)) {
|
||||||
|
@SuppressWarnings("unchecked") // clone class <= object class <= T
|
||||||
|
T t = (T) clone;
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
throw new ClassCastException(clone.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void rethrow(Throwable cause) throws CloneNotSupportedException {
|
||||||
|
if (cause instanceof RuntimeException) {
|
||||||
|
throw (RuntimeException) cause;
|
||||||
|
}
|
||||||
|
if (cause instanceof Error) {
|
||||||
|
throw (Error) cause;
|
||||||
|
}
|
||||||
|
if (cause instanceof CloneNotSupportedException) {
|
||||||
|
throw (CloneNotSupportedException) cause;
|
||||||
|
}
|
||||||
|
CloneNotSupportedException e = new CloneNotSupportedException();
|
||||||
|
e.initCause(cause);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,4 +252,29 @@ public final class Constraints {
|
||||||
*/
|
*/
|
||||||
int flags();
|
int flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distinct annotation is used to signal, but not ensure that a value should be
|
||||||
|
* distinct in the database.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Can be used only for @java.lang.CharSequence
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* It does not have effect on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = DistinctValidator.class)
|
||||||
|
public @interface Distinct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User defined Enum to further restrict the items in the set.
|
||||||
|
*
|
||||||
|
* @return Java
|
||||||
|
*/
|
||||||
|
Class<? extends Enum> value() default Enum.class;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,10 @@ public @interface Index {
|
||||||
* @return true if the index should ignore case when comparing
|
* @return true if the index should ignore case when comparing
|
||||||
*/
|
*/
|
||||||
boolean caseSensitive() default true;
|
boolean caseSensitive() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean distinct() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Helenus 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 net.helenus.mapping.validator;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
import net.helenus.mapping.annotation.Constraints;
|
||||||
|
|
||||||
|
public final class DistinctValidator implements ConstraintValidator<Constraints.Distinct, CharSequence> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(Constraints.Distinct constraintAnnotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
|
||||||
|
// TODO(gburd): if there is an Enum type supplied, check that value is valid
|
||||||
|
// Enum.name()
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,87 +15,83 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.build;
|
package net.helenus.test.integration.build;
|
||||||
|
|
||||||
import com.datastax.driver.core.Cluster;
|
|
||||||
import com.datastax.driver.core.KeyspaceMetadata;
|
|
||||||
import com.datastax.driver.core.Session;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.cassandra.exceptions.ConfigurationException;
|
import org.apache.cassandra.exceptions.ConfigurationException;
|
||||||
import org.apache.thrift.transport.TTransportException;
|
import org.apache.thrift.transport.TTransportException;
|
||||||
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
|
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.Cluster;
|
||||||
|
import com.datastax.driver.core.KeyspaceMetadata;
|
||||||
|
import com.datastax.driver.core.Session;
|
||||||
|
|
||||||
/** AbstractEmbeddedCassandraTest */
|
/** AbstractEmbeddedCassandraTest */
|
||||||
public abstract class AbstractEmbeddedCassandraTest {
|
public abstract class AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
private static Cluster cluster;
|
private static Cluster cluster;
|
||||||
|
|
||||||
private static String keyspace;
|
private static String keyspace;
|
||||||
|
|
||||||
private static Session session;
|
private static Session session;
|
||||||
|
|
||||||
private static boolean keep;
|
private static boolean keep;
|
||||||
|
|
||||||
public static boolean isConnected() {
|
public static boolean isConnected() {
|
||||||
return session != null;
|
return session != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cluster getCluster() {
|
public static Cluster getCluster() {
|
||||||
return cluster;
|
return cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Session getSession() {
|
public static Session getSession() {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getKeyspace() {
|
public static String getKeyspace() {
|
||||||
return keyspace;
|
return keyspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setKeep(boolean enable) {
|
public static void setKeep(boolean enable) {
|
||||||
keep = enable;
|
keep = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void startCassandraEmbeddedServer()
|
public static void startCassandraEmbeddedServer()
|
||||||
throws TTransportException, IOException, InterruptedException, ConfigurationException {
|
throws TTransportException, IOException, InterruptedException, ConfigurationException {
|
||||||
keyspace = "test" + UUID.randomUUID().toString().replace("-", "");
|
keyspace = "test" + UUID.randomUUID().toString().replace("-", "");
|
||||||
EmbeddedCassandraServerHelper.startEmbeddedCassandra(
|
EmbeddedCassandraServerHelper.startEmbeddedCassandra(EmbeddedCassandraServerHelper.CASSANDRA_RNDPORT_YML_FILE);
|
||||||
EmbeddedCassandraServerHelper.CASSANDRA_RNDPORT_YML_FILE);
|
|
||||||
|
|
||||||
cluster =
|
cluster = Cluster.builder().addContactPoint(EmbeddedCassandraServerHelper.getHost())
|
||||||
Cluster.builder()
|
.withPort(EmbeddedCassandraServerHelper.getNativeTransportPort()).build();
|
||||||
.addContactPoint(EmbeddedCassandraServerHelper.getHost())
|
|
||||||
.withPort(EmbeddedCassandraServerHelper.getNativeTransportPort())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace);
|
KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace);
|
||||||
if (kmd == null) {
|
if (kmd == null) {
|
||||||
session = cluster.connect();
|
session = cluster.connect();
|
||||||
|
|
||||||
String cql =
|
String cql = "CREATE KEYSPACE " + keyspace
|
||||||
"CREATE KEYSPACE "
|
+ " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}"
|
||||||
+ keyspace
|
+ " AND DURABLE_WRITES = false;";
|
||||||
+ " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1}"
|
System.out.println(cql + "\n");
|
||||||
+ " AND DURABLE_WRITES = false;";
|
session.execute(cql);
|
||||||
System.out.println(cql + "\n");
|
|
||||||
session.execute(cql);
|
|
||||||
|
|
||||||
cql = "USE " + keyspace + ";";
|
cql = "USE " + keyspace + ";";
|
||||||
System.out.println(cql + "\n");
|
System.out.println(cql + "\n");
|
||||||
session.execute(cql);
|
session.execute(cql);
|
||||||
} else {
|
} else {
|
||||||
session = cluster.connect(keyspace);
|
session = cluster.connect(keyspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void after() {
|
public static void after() {
|
||||||
if (!keep && isConnected()) {
|
if (!keep && isConnected()) {
|
||||||
session.close();
|
session.close();
|
||||||
session = null;
|
session = null;
|
||||||
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
|
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core;
|
package net.helenus.test.integration.core;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class ContextInitTest extends AbstractEmbeddedCassandraTest {
|
public class ContextInitTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
||||||
HelenusSession session = Helenus.init(getSession()).get();
|
HelenusSession session = Helenus.init(getSession()).get();
|
||||||
|
|
||||||
System.out.println("Works! " + session);
|
System.out.println("Works! " + session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package net.helenus.test.integration.core;
|
package net.helenus.test.integration.core;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusValidator;
|
import net.helenus.core.HelenusValidator;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
@ -10,43 +13,40 @@ import net.helenus.mapping.annotation.Table;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class HelenusValidatorTest extends AbstractEmbeddedCassandraTest {
|
public class HelenusValidatorTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
@Table
|
HelenusEntity entity;
|
||||||
interface ModelForValidation {
|
HelenusProperty prop;
|
||||||
|
|
||||||
@Constraints.Email
|
@Before
|
||||||
@PartitionKey
|
public void begin() {
|
||||||
String id();
|
Helenus.init(getSession()).singleton();
|
||||||
}
|
|
||||||
|
|
||||||
HelenusEntity entity;
|
entity = Helenus.entity(ModelForValidation.class);
|
||||||
|
|
||||||
HelenusProperty prop;
|
prop = entity.getProperty("id");
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Test(expected = HelenusMappingException.class)
|
||||||
public void begin() {
|
public void testWrongType() {
|
||||||
Helenus.init(getSession()).singleton();
|
HelenusValidator.INSTANCE.validate(prop, Integer.valueOf(123));
|
||||||
|
}
|
||||||
|
|
||||||
entity = Helenus.entity(ModelForValidation.class);
|
@Test(expected = HelenusException.class)
|
||||||
|
public void testWrongValue() {
|
||||||
|
HelenusValidator.INSTANCE.validate(prop, "123");
|
||||||
|
}
|
||||||
|
|
||||||
prop = entity.getProperty("id");
|
public void testOk() {
|
||||||
}
|
HelenusValidator.INSTANCE.validate(prop, "a@b.c");
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = HelenusMappingException.class)
|
@Table
|
||||||
public void testWrongType() {
|
interface ModelForValidation {
|
||||||
HelenusValidator.INSTANCE.validate(prop, Integer.valueOf(123));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HelenusException.class)
|
@Constraints.Email
|
||||||
public void testWrongValue() {
|
@PartitionKey
|
||||||
HelenusValidator.INSTANCE.validate(prop, "123");
|
String id();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOk() {
|
|
||||||
HelenusValidator.INSTANCE.validate(prop, "a@b.c");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,407 +15,340 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.collection;
|
package net.helenus.test.integration.core.collection;
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
import static net.helenus.core.Query.*;
|
||||||
import static net.helenus.core.Query.get;
|
|
||||||
import static net.helenus.core.Query.getIdx;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Customer customer;
|
static Customer customer;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(Customer.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Customer.class).autoCreateDrop().get();
|
||||||
customer = Helenus.dsl(Customer.class, session.getMetadata());
|
customer = Helenus.dsl(Customer.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(customer);
|
System.out.println(customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetCRUID() throws TimeoutException {
|
public void testSetCRUID() throws TimeoutException {
|
||||||
|
|
||||||
UUID id = UUID.randomUUID();
|
UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
Set<String> aliases = new HashSet<String>();
|
Set<String> aliases = new HashSet<String>();
|
||||||
aliases.add("Alex");
|
aliases.add("Alex");
|
||||||
aliases.add("Albert");
|
aliases.add("Albert");
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(customer::id, id).value(customer::aliases, aliases).sync();
|
session.insert().value(customer::id, id).value(customer::aliases, aliases).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual =
|
Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(aliases, actual.aliases());
|
||||||
Assert.assertEquals(aliases, actual.aliases());
|
Assert.assertNull(actual.names());
|
||||||
Assert.assertNull(actual.names());
|
Assert.assertNull(actual.properties());
|
||||||
Assert.assertNull(actual.properties());
|
|
||||||
|
|
||||||
// read full set
|
// read full set
|
||||||
|
|
||||||
Set<String> actualSet =
|
Set<String> actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst()
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
Assert.assertEquals(aliases, actualSet);
|
Assert.assertEquals(aliases, actualSet);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Set<String> expected = new HashSet<String>();
|
Set<String> expected = new HashSet<String>();
|
||||||
expected.add("unknown");
|
expected.add("unknown");
|
||||||
|
|
||||||
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
|
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(expected, actual.aliases());
|
Assert.assertEquals(expected, actual.aliases());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// add operation
|
// add operation
|
||||||
|
|
||||||
expected.add("add");
|
expected.add("add");
|
||||||
session.update().add(customer::aliases, "add").where(customer::id, eq(id)).sync();
|
session.update().add(customer::aliases, "add").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualSet);
|
||||||
Assert.assertEquals(expected, actualSet);
|
|
||||||
|
|
||||||
// addAll operation
|
// addAll operation
|
||||||
expected.addAll(aliases);
|
expected.addAll(aliases);
|
||||||
session.update().addAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
|
session.update().addAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualSet);
|
||||||
Assert.assertEquals(expected, actualSet);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
expected.remove("add");
|
expected.remove("add");
|
||||||
session.update().remove(customer::aliases, "add").where(customer::id, eq(id)).sync();
|
session.update().remove(customer::aliases, "add").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualSet);
|
||||||
Assert.assertEquals(expected, actualSet);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.removeAll(aliases);
|
expected.removeAll(aliases);
|
||||||
session.update().removeAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
|
session.update().removeAll(customer::aliases, aliases).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualSet);
|
||||||
Assert.assertEquals(expected, actualSet);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(customer::aliases, null).where(customer::id, eq(id)).sync();
|
session.update().set(customer::aliases, null).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualSet);
|
||||||
Assert.assertNull(actualSet);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(customer::id, eq(id)).sync();
|
session.delete().where(customer::id, eq(id)).sync();
|
||||||
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListCRUID() throws TimeoutException {
|
public void testListCRUID() throws TimeoutException {
|
||||||
|
|
||||||
UUID id = UUID.randomUUID();
|
UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
List<String> names = new ArrayList<String>();
|
List<String> names = new ArrayList<String>();
|
||||||
names.add("Alex");
|
names.add("Alex");
|
||||||
names.add("Albert");
|
names.add("Albert");
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(customer::id, id).value(customer::names, names).sync();
|
session.insert().value(customer::id, id).value(customer::names, names).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual =
|
Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(names, actual.names());
|
Assert.assertEquals(names, actual.names());
|
||||||
Assert.assertNull(actual.aliases());
|
Assert.assertNull(actual.aliases());
|
||||||
Assert.assertNull(actual.properties());
|
Assert.assertNull(actual.properties());
|
||||||
|
|
||||||
// read full list
|
// read full list
|
||||||
|
|
||||||
List<String> actualList =
|
List<String> actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst()
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
Assert.assertEquals(names, actualList);
|
Assert.assertEquals(names, actualList);
|
||||||
|
|
||||||
// read single value by index
|
// read single value by index
|
||||||
|
|
||||||
String cql = session.select(getIdx(customer::names, 1)).where(customer::id, eq(id)).cql();
|
String cql = session.select(getIdx(customer::names, 1)).where(customer::id, eq(id)).cql();
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
List<String> expected = new ArrayList<String>();
|
List<String> expected = new ArrayList<String>();
|
||||||
expected.add("unknown");
|
expected.add("unknown");
|
||||||
|
|
||||||
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
|
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(expected, actual.names());
|
Assert.assertEquals(expected, actual.names());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// prepend operation
|
// prepend operation
|
||||||
|
|
||||||
expected.add(0, "prepend");
|
expected.add(0, "prepend");
|
||||||
session.update().prepend(customer::names, "prepend").where(customer::id, eq(id)).sync();
|
session.update().prepend(customer::names, "prepend").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// append operation
|
// append operation
|
||||||
|
|
||||||
expected.add("append");
|
expected.add("append");
|
||||||
session.update().append(customer::names, "append").where(customer::id, eq(id)).sync();
|
session.update().append(customer::names, "append").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// prependAll operation
|
// prependAll operation
|
||||||
expected.addAll(0, names);
|
expected.addAll(0, names);
|
||||||
session.update().prependAll(customer::names, names).where(customer::id, eq(id)).sync();
|
session.update().prependAll(customer::names, names).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// appendAll operation
|
// appendAll operation
|
||||||
expected.addAll(names);
|
expected.addAll(names);
|
||||||
session.update().appendAll(customer::names, names).where(customer::id, eq(id)).sync();
|
session.update().appendAll(customer::names, names).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// set by Index
|
// set by Index
|
||||||
|
|
||||||
expected.set(5, "inserted");
|
expected.set(5, "inserted");
|
||||||
session.update().setIdx(customer::names, 5, "inserted").where(customer::id, eq(id)).sync();
|
session.update().setIdx(customer::names, 5, "inserted").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
expected.remove("inserted");
|
expected.remove("inserted");
|
||||||
session.update().discard(customer::names, "inserted").where(customer::id, eq(id)).sync();
|
session.update().discard(customer::names, "inserted").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.removeAll(names);
|
expected.removeAll(names);
|
||||||
session.update().discardAll(customer::names, names).where(customer::id, eq(id)).sync();
|
session.update().discardAll(customer::names, names).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertEquals(expected, actualList);
|
||||||
Assert.assertEquals(expected, actualList);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(customer::names, null).where(customer::id, eq(id)).sync();
|
session.update().set(customer::names, null).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualList);
|
||||||
Assert.assertNull(actualList);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(customer::id, eq(id)).sync();
|
session.delete().where(customer::id, eq(id)).sync();
|
||||||
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMapCRUID() throws TimeoutException {
|
public void testMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
UUID id = UUID.randomUUID();
|
UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
Map<String, String> props = new HashMap<String, String>();
|
Map<String, String> props = new HashMap<String, String>();
|
||||||
props.put("key1", "value1");
|
props.put("key1", "value1");
|
||||||
props.put("key2", "value2");
|
props.put("key2", "value2");
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(customer::id, id).value(customer::properties, props).sync();
|
session.insert().value(customer::id, id).value(customer::properties, props).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual =
|
Customer actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(props, actual.properties());
|
Assert.assertEquals(props, actual.properties());
|
||||||
Assert.assertNull(actual.aliases());
|
Assert.assertNull(actual.aliases());
|
||||||
Assert.assertNull(actual.names());
|
Assert.assertNull(actual.names());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<String, String> actualMap =
|
Map<String, String> actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync()
|
||||||
session
|
.findFirst().get()._1;
|
||||||
.select(customer::properties)
|
Assert.assertEquals(props, actualMap);
|
||||||
.where(customer::id, eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertEquals(props, actualMap);
|
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql =
|
String cql = session.select(get(customer::properties, "key1")).where(customer::id, eq(id)).cql();
|
||||||
session.select(get(customer::properties, "key1")).where(customer::id, eq(id)).cql();
|
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<String, String> expected = new HashMap<String, String>();
|
Map<String, String> expected = new HashMap<String, String>();
|
||||||
expected.put("k1", "v1");
|
expected.put("k1", "v1");
|
||||||
expected.put("k2", "v2");
|
expected.put("k2", "v2");
|
||||||
|
|
||||||
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
|
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(expected, actual.properties());
|
||||||
Assert.assertEquals(expected, actual.properties());
|
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
expected.put("k3", "v3");
|
expected.put("k3", "v3");
|
||||||
session.update().put(customer::properties, "k3", "v3").where(customer::id, eq(id)).sync();
|
session.update().put(customer::properties, "k3", "v3").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session
|
Assert.assertEquals(expected, actualMap);
|
||||||
.select(customer::properties)
|
|
||||||
.where(customer::id, eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertEquals(expected, actualMap);
|
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(props);
|
expected.putAll(props);
|
||||||
session.update().putAll(customer::properties, props).where(customer::id, eq(id)).sync();
|
session.update().putAll(customer::properties, props).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session
|
Assert.assertEquals(expected, actualMap);
|
||||||
.select(customer::properties)
|
|
||||||
.where(customer::id, eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertEquals(expected, actualMap);
|
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
expected.put("k3", "v33");
|
expected.put("k3", "v33");
|
||||||
session.update().put(customer::properties, "k3", "v33").where(customer::id, eq(id)).sync();
|
session.update().put(customer::properties, "k3", "v33").where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session
|
Assert.assertEquals(expected, actualMap);
|
||||||
.select(customer::properties)
|
|
||||||
.where(customer::id, eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertEquals(expected, actualMap);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove("k3");
|
expected.remove("k3");
|
||||||
session.update().put(customer::properties, "k3", null).where(customer::id, eq(id)).sync();
|
session.update().put(customer::properties, "k3", null).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
session
|
Assert.assertEquals(expected, actualMap);
|
||||||
.select(customer::properties)
|
|
||||||
.where(customer::id, eq(id))
|
// remove full map
|
||||||
.sync()
|
|
||||||
.findFirst()
|
session.update().set(customer::properties, null).where(customer::id, eq(id)).sync();
|
||||||
.get()
|
|
||||||
._1;
|
actualMap = session.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1;
|
||||||
Assert.assertEquals(expected, actualMap);
|
Assert.assertNull(actualMap);
|
||||||
|
|
||||||
// remove full map
|
// remove object
|
||||||
|
|
||||||
session.update().set(customer::properties, null).where(customer::id, eq(id)).sync();
|
session.delete().where(customer::id, eq(id)).sync();
|
||||||
|
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
||||||
actualMap =
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
session
|
}
|
||||||
.select(customer::properties)
|
|
||||||
.where(customer::id, eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertNull(actualMap);
|
|
||||||
|
|
||||||
// remove object
|
|
||||||
|
|
||||||
session.delete().where(customer::id, eq(id)).sync();
|
|
||||||
Long cnt = session.count().where(customer::id, eq(id)).sync();
|
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.collection;
|
package net.helenus.test.integration.core.collection;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType.Name;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.DataType.Name;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
import net.helenus.mapping.annotation.Types;
|
import net.helenus.mapping.annotation.Types;
|
||||||
|
@ -27,15 +29,15 @@ import net.helenus.mapping.annotation.Types;
|
||||||
@Table
|
@Table
|
||||||
public interface Customer {
|
public interface Customer {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID id();
|
UUID id();
|
||||||
|
|
||||||
@Types.Set(Name.TEXT)
|
@Types.Set(Name.TEXT)
|
||||||
Set<String> aliases();
|
Set<String> aliases();
|
||||||
|
|
||||||
@Types.List(Name.TEXT)
|
@Types.List(Name.TEXT)
|
||||||
List<String> names();
|
List<String> names();
|
||||||
|
|
||||||
@Types.Map(key = Name.TEXT, value = Name.TEXT)
|
@Types.Map(key = Name.TEXT, value = Name.TEXT)
|
||||||
Map<String, String> properties();
|
Map<String, String> properties();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,92 +17,89 @@ package net.helenus.test.integration.core.compound;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.Operator;
|
import net.helenus.core.Operator;
|
||||||
import net.helenus.core.Query;
|
import net.helenus.core.Query;
|
||||||
import net.helenus.support.Mutable;
|
import net.helenus.support.Mutable;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
|
public class CompondKeyTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
Timeline timeline;
|
Timeline timeline;
|
||||||
|
|
||||||
HelenusSession session;
|
HelenusSession session;
|
||||||
|
|
||||||
public static class TimelineImpl implements Timeline {
|
@Before
|
||||||
|
public void beforeTest() {
|
||||||
|
session = Helenus.init(getSession()).showCql().add(Timeline.class).autoCreateDrop().get();
|
||||||
|
timeline = Helenus.dsl(Timeline.class, session.getMetadata());
|
||||||
|
}
|
||||||
|
|
||||||
UUID userId;
|
@Test
|
||||||
Date timestamp;
|
public void test() throws Exception {
|
||||||
String text;
|
|
||||||
|
|
||||||
@Override
|
UUID userId = UUID.randomUUID();
|
||||||
public UUID userId() {
|
long postTime = System.currentTimeMillis() - 100000L;
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
session.showCql(false);
|
||||||
public Date timestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
for (int i = 0; i != 100; ++i) {
|
||||||
public String text() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
TimelineImpl post = new TimelineImpl();
|
||||||
public void beforeTest() {
|
post.userId = userId;
|
||||||
session = Helenus.init(getSession()).showCql().add(Timeline.class).autoCreateDrop().get();
|
post.timestamp = new Date(postTime + 1000L * i);
|
||||||
timeline = Helenus.dsl(Timeline.class, session.getMetadata());
|
post.text = "hello";
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
session.upsert(post).sync();
|
||||||
public void test() throws Exception {
|
}
|
||||||
|
|
||||||
UUID userId = UUID.randomUUID();
|
session.showCql(true);
|
||||||
long postTime = System.currentTimeMillis() - 100000L;
|
|
||||||
|
|
||||||
session.showCql(false);
|
final Mutable<Date> d = new Mutable<Date>(null);
|
||||||
|
final Mutable<Integer> c = new Mutable<Integer>(0);
|
||||||
|
|
||||||
for (int i = 0; i != 100; ++i) {
|
session.select(timeline::userId, timeline::timestamp, timeline::text)
|
||||||
|
.where(timeline::userId, Operator.EQ, userId).orderBy(Query.desc(timeline::timestamp)).limit(5).sync()
|
||||||
|
.forEach(t -> {
|
||||||
|
|
||||||
TimelineImpl post = new TimelineImpl();
|
// System.out.println(t);
|
||||||
post.userId = userId;
|
c.set(c.get() + 1);
|
||||||
post.timestamp = new Date(postTime + 1000L * i);
|
|
||||||
post.text = "hello";
|
|
||||||
|
|
||||||
session.upsert(post).sync();
|
Date cd = d.get();
|
||||||
}
|
if (cd != null) {
|
||||||
|
Assert.assertTrue(cd.after(t._2));
|
||||||
|
}
|
||||||
|
d.set(t._2);
|
||||||
|
});
|
||||||
|
|
||||||
session.showCql(true);
|
Assert.assertEquals(Integer.valueOf(5), c.get());
|
||||||
|
}
|
||||||
|
|
||||||
final Mutable<Date> d = new Mutable<Date>(null);
|
public static class TimelineImpl implements Timeline {
|
||||||
final Mutable<Integer> c = new Mutable<Integer>(0);
|
|
||||||
|
|
||||||
session
|
UUID userId;
|
||||||
.select(timeline::userId, timeline::timestamp, timeline::text)
|
Date timestamp;
|
||||||
.where(timeline::userId, Operator.EQ, userId)
|
String text;
|
||||||
.orderBy(Query.desc(timeline::timestamp))
|
|
||||||
.limit(5)
|
|
||||||
.sync()
|
|
||||||
.forEach(
|
|
||||||
t -> {
|
|
||||||
|
|
||||||
//System.out.println(t);
|
@Override
|
||||||
c.set(c.get() + 1);
|
public UUID userId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
Date cd = d.get();
|
@Override
|
||||||
if (cd != null) {
|
public Date timestamp() {
|
||||||
Assert.assertTrue(cd.after(t._2));
|
return timestamp;
|
||||||
}
|
}
|
||||||
d.set(t._2);
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.assertEquals(Integer.valueOf(5), c.get());
|
@Override
|
||||||
}
|
public String text() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,22 +17,19 @@ package net.helenus.test.integration.core.compound;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.helenus.mapping.annotation.ClusteringColumn;
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.*;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
|
||||||
import net.helenus.mapping.annotation.Table;
|
|
||||||
import net.helenus.mapping.annotation.Types;
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Timeline {
|
public interface Timeline {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
UUID userId();
|
UUID userId();
|
||||||
|
|
||||||
@ClusteringColumn(ordinal = 1)
|
@ClusteringColumn(ordinal = 1)
|
||||||
@Types.Timeuuid
|
@Types.Timeuuid
|
||||||
Date timestamp();
|
Date timestamp();
|
||||||
|
|
||||||
@Column(ordinal = 2)
|
@Column(ordinal = 2)
|
||||||
String text();
|
String text();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,46 +18,46 @@ package net.helenus.test.integration.core.counter;
|
||||||
import static net.helenus.core.Query.eq;
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class CounterTest extends AbstractEmbeddedCassandraTest {
|
public class CounterTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Page page;
|
static Page page;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(Page.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Page.class).autoCreateDrop().get();
|
||||||
page = Helenus.dsl(Page.class, session.getMetadata());
|
page = Helenus.dsl(Page.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(page);
|
System.out.println(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() throws TimeoutException {
|
public void testCounter() throws TimeoutException {
|
||||||
|
|
||||||
boolean exists =
|
boolean exists = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().isPresent();
|
||||||
session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().isPresent();
|
Assert.assertFalse(exists);
|
||||||
Assert.assertFalse(exists);
|
|
||||||
|
|
||||||
session.update().increment(page::hits, 10L).where(page::alias, eq("index")).sync();
|
session.update().increment(page::hits, 10L).where(page::alias, eq("index")).sync();
|
||||||
|
|
||||||
long hits =
|
long hits = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
|
||||||
session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
|
Assert.assertEquals(10, hits);
|
||||||
Assert.assertEquals(10, hits);
|
|
||||||
|
|
||||||
session.update().decrement(page::hits).where(page::alias, eq("index")).sync();
|
session.update().decrement(page::hits).where(page::alias, eq("index")).sync();
|
||||||
|
|
||||||
hits = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
|
hits = session.select(page::hits).where(page::alias, eq("index")).sync().findFirst().get()._1;
|
||||||
Assert.assertEquals(9, hits);
|
Assert.assertEquals(9, hits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ import net.helenus.mapping.annotation.Types;
|
||||||
@Table
|
@Table
|
||||||
public interface Page {
|
public interface Page {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
String alias();
|
String alias();
|
||||||
|
|
||||||
@Types.Counter
|
@Types.Counter
|
||||||
long hits();
|
long hits();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,75 +15,100 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.draft;
|
package net.helenus.test.integration.core.draft;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import net.helenus.core.Helenus;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
|
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Supply supply;
|
static Supply supply;
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
static Supply.Draft draft = null;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() throws TimeoutException {
|
||||||
session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get();
|
||||||
supply = session.dsl(Supply.class);
|
supply = session.dsl(Supply.class);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
draft = Supply.draft("APAC").code("WIDGET-002").description("Our second Widget!")
|
||||||
public void testFoo() throws Exception {
|
.demand(new HashMap<String, Long>() {
|
||||||
Supply.Draft draft = null;
|
{
|
||||||
|
put("APAC", 100L);
|
||||||
draft =
|
put("EMEA", 10000L);
|
||||||
Supply.draft("APAC")
|
put("NORAM", 2000000L);
|
||||||
.code("WIDGET-002")
|
}
|
||||||
.description("Our second Widget!")
|
}).shipments(new HashSet<String>() {
|
||||||
.demand(
|
{
|
||||||
new HashMap<String, Long>() {
|
add("HMS Puddle in transit to APAC, 100 units.");
|
||||||
{
|
add("Frigate Jimmy in transit to EMEA, 10000 units.");
|
||||||
put("APAC", 100L);
|
}
|
||||||
put("EMEA", 10000L);
|
}).suppliers(new ArrayList<String>() {
|
||||||
put("NORAM", 2000000L);
|
{
|
||||||
}
|
add("Puddle, Inc.");
|
||||||
})
|
add("Jimmy Town, LTD.");
|
||||||
.shipments(
|
}
|
||||||
new HashSet<String>() {
|
|
||||||
{
|
|
||||||
add("HMS Puddle in transit to APAC, 100 units.");
|
|
||||||
add("Frigate Jimmy in transit to EMEA, 10000 units.");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.suppliers(
|
|
||||||
new ArrayList<String>() {
|
|
||||||
{
|
|
||||||
add("Puddle, Inc.");
|
|
||||||
add("Jimmy Town, LTD.");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Supply s1 = session.<Supply>insert(draft).sync();
|
Supply s1 = session.<Supply>insert(draft).sync();
|
||||||
|
}
|
||||||
|
|
||||||
// List
|
@Test
|
||||||
Supply s2 =
|
public void testFoo() throws Exception {
|
||||||
session
|
|
||||||
.<Supply>update(s1.update())
|
|
||||||
.prepend(supply::suppliers, "Pignose Supply, LLC.")
|
|
||||||
.sync();
|
|
||||||
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
|
|
||||||
|
|
||||||
// Set
|
Supply s1 = session.<Supply>select(Supply.class).where(supply::id, eq(draft.id()))
|
||||||
String shipment = "Pignose, on the way! (1M units)";
|
.single()
|
||||||
Supply s3 = session.<Supply>update(s2.update()).add(supply::shipments, shipment).sync();
|
.sync()
|
||||||
Assert.assertTrue(s3.shipments().contains(shipment));
|
.orElse(null);
|
||||||
|
|
||||||
// Map
|
// List
|
||||||
Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
|
Supply s2 = session.<Supply>update(s1.update()).prepend(supply::suppliers, "Pignose Supply, LLC.").sync();
|
||||||
Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
|
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
|
||||||
}
|
|
||||||
|
// Set
|
||||||
|
String shipment = "Pignose, on the way! (1M units)";
|
||||||
|
Supply s3 = session.<Supply>update(s2.update()).add(supply::shipments, shipment).sync();
|
||||||
|
Assert.assertTrue(s3.shipments().contains(shipment));
|
||||||
|
|
||||||
|
// Map
|
||||||
|
Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
|
||||||
|
Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSerialization() throws Exception {
|
||||||
|
Supply s1, s2;
|
||||||
|
|
||||||
|
s1 = session.<Supply>select(Supply.class).where(supply::id, eq(draft.id()))
|
||||||
|
.single()
|
||||||
|
.sync()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
byte[] data;
|
||||||
|
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
ObjectOutput out = new ObjectOutputStream(bos)) {
|
||||||
|
out.writeObject(s1);
|
||||||
|
out.flush();
|
||||||
|
data = bos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||||
|
ObjectInput in = new ObjectInputStream(bis)) {
|
||||||
|
s2 = (Supply)in.readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertEquals(s2.id(), s1.id());
|
||||||
|
Assert.assertEquals(s2, s1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.helenus.test.integration.core.draft;
|
package net.helenus.test.integration.core.draft;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.helenus.core.AbstractAuditedEntityDraft;
|
import net.helenus.core.AbstractAuditedEntityDraft;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
|
@ -9,85 +10,85 @@ import net.helenus.mapping.annotation.*;
|
||||||
@Table
|
@Table
|
||||||
public interface Inventory {
|
public interface Inventory {
|
||||||
|
|
||||||
static Inventory inventory = Helenus.dsl(Inventory.class);
|
static Inventory inventory = Helenus.dsl(Inventory.class);
|
||||||
|
|
||||||
@PartitionKey
|
@Transient
|
||||||
UUID id();
|
static Draft draft(UUID id) {
|
||||||
|
return new Draft(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Column("emea")
|
@PartitionKey
|
||||||
@Types.Counter
|
UUID id();
|
||||||
long EMEA();
|
|
||||||
|
|
||||||
@Column("noram")
|
@Column("emea")
|
||||||
@Types.Counter
|
@Types.Counter
|
||||||
long NORAM();
|
long EMEA();
|
||||||
|
|
||||||
@Column("apac")
|
@Column("noram")
|
||||||
@Types.Counter
|
@Types.Counter
|
||||||
long APAC();
|
long NORAM();
|
||||||
|
|
||||||
@Transient
|
@Column("apac")
|
||||||
static Draft draft(UUID id) {
|
@Types.Counter
|
||||||
return new Draft(id);
|
long APAC();
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
default Draft update() {
|
default Draft update() {
|
||||||
return new Draft(this);
|
return new Draft(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Draft extends AbstractAuditedEntityDraft<Inventory> {
|
class Draft extends AbstractAuditedEntityDraft<Inventory> {
|
||||||
|
|
||||||
// Entity/Draft pattern-enabling methods:
|
// Entity/Draft pattern-enabling methods:
|
||||||
Draft(UUID id) {
|
Draft(UUID id) {
|
||||||
super(null);
|
super(null);
|
||||||
|
|
||||||
// Primary Key:
|
// Primary Key:
|
||||||
set(inventory::id, id);
|
set(inventory::id, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Draft(Inventory inventory) {
|
Draft(Inventory inventory) {
|
||||||
super((MapExportable) inventory);
|
super((MapExportable) inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<Inventory> getEntityClass() {
|
public Class<Inventory> getEntityClass() {
|
||||||
return Inventory.class;
|
return Inventory.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getCurrentAuditor() {
|
protected String getCurrentAuditor() {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immutable properties:
|
// Immutable properties:
|
||||||
public UUID id() {
|
public UUID id() {
|
||||||
return this.<UUID>get(inventory::id, UUID.class);
|
return this.<UUID>get(inventory::id, UUID.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long EMEA() {
|
public long EMEA() {
|
||||||
return this.<Long>get(inventory::EMEA, long.class);
|
return this.<Long>get(inventory::EMEA, long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft EMEA(long count) {
|
public Draft EMEA(long count) {
|
||||||
mutate(inventory::EMEA, count);
|
mutate(inventory::EMEA, count);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long APAC() {
|
public long APAC() {
|
||||||
return this.<Long>get(inventory::APAC, long.class);
|
return this.<Long>get(inventory::APAC, long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft APAC(long count) {
|
public Draft APAC(long count) {
|
||||||
mutate(inventory::APAC, count);
|
mutate(inventory::APAC, count);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long NORAM() {
|
public long NORAM() {
|
||||||
return this.<Long>get(inventory::NORAM, long.class);
|
return this.<Long>get(inventory::NORAM, long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft NORAM(long count) {
|
public Draft NORAM(long count) {
|
||||||
mutate(inventory::NORAM, count);
|
mutate(inventory::NORAM, count);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package net.helenus.test.integration.core.draft;
|
package net.helenus.test.integration.core.draft;
|
||||||
|
|
||||||
import com.datastax.driver.core.utils.UUIDs;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.utils.UUIDs;
|
||||||
|
|
||||||
import net.helenus.core.AbstractEntityDraft;
|
import net.helenus.core.AbstractEntityDraft;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
|
@ -13,133 +15,133 @@ import net.helenus.mapping.annotation.*;
|
||||||
@Table
|
@Table
|
||||||
public interface Supply {
|
public interface Supply {
|
||||||
|
|
||||||
static Supply supply = Helenus.dsl(Supply.class);
|
static Supply supply = Helenus.dsl(Supply.class);
|
||||||
|
|
||||||
@PartitionKey
|
@Transient
|
||||||
UUID id();
|
static Draft draft(String region) {
|
||||||
|
return new Draft(region);
|
||||||
|
}
|
||||||
|
|
||||||
@ClusteringColumn(ordinal = 0)
|
@PartitionKey
|
||||||
default String region() {
|
UUID id();
|
||||||
return "NORAM";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Index(caseSensitive = false)
|
@ClusteringColumn(ordinal = 0)
|
||||||
String code();
|
default String region() {
|
||||||
|
return "NORAM";
|
||||||
|
}
|
||||||
|
|
||||||
@Index
|
@Index(caseSensitive = false)
|
||||||
String description(); // @IndexText == lucene index
|
String code();
|
||||||
|
|
||||||
@Index
|
@Index
|
||||||
Map<String, Long> demand();
|
String description(); // @IndexText == lucene index
|
||||||
|
|
||||||
@Index
|
@Index
|
||||||
List<String> suppliers();
|
Map<String, Long> demand();
|
||||||
|
|
||||||
@Index
|
@Index
|
||||||
Set<String> shipments();
|
List<String> suppliers();
|
||||||
|
|
||||||
@Transient
|
@Index
|
||||||
static Draft draft(String region) {
|
Set<String> shipments();
|
||||||
return new Draft(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
default Draft update() {
|
default Draft update() {
|
||||||
return new Draft(this);
|
return new Draft(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Draft extends AbstractEntityDraft<Supply> {
|
class Draft extends AbstractEntityDraft<Supply> {
|
||||||
|
|
||||||
// Entity/Draft pattern-enabling methods:
|
// Entity/Draft pattern-enabling methods:
|
||||||
Draft(String region) {
|
Draft(String region) {
|
||||||
super(null);
|
super(null);
|
||||||
|
|
||||||
// Primary Key:
|
// Primary Key:
|
||||||
set(supply::id, UUIDs.timeBased());
|
set(supply::id, UUIDs.timeBased());
|
||||||
set(supply::region, region);
|
set(supply::region, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
Draft(Supply supply) {
|
Draft(Supply supply) {
|
||||||
super((MapExportable) supply);
|
super((MapExportable) supply);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<Supply> getEntityClass() {
|
public Class<Supply> getEntityClass() {
|
||||||
return Supply.class;
|
return Supply.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immutable properties:
|
// Immutable properties:
|
||||||
public UUID id() {
|
public UUID id() {
|
||||||
return this.<UUID>get(supply::id, UUID.class);
|
return this.<UUID>get(supply::id, UUID.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String region() {
|
public String region() {
|
||||||
return this.<String>get(supply::region, String.class);
|
return this.<String>get(supply::region, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutable properties:
|
// Mutable properties:
|
||||||
public String code() {
|
public String code() {
|
||||||
return this.<String>get(supply::code, String.class);
|
return this.<String>get(supply::code, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft code(String code) {
|
public Draft code(String code) {
|
||||||
mutate(supply::code, code);
|
mutate(supply::code, code);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft setCode(String code) {
|
public Draft setCode(String code) {
|
||||||
return code(code);
|
return code(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String description() {
|
public String description() {
|
||||||
return this.<String>get(supply::description, String.class);
|
return this.<String>get(supply::description, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft description(String description) {
|
public Draft description(String description) {
|
||||||
mutate(supply::description, description);
|
mutate(supply::description, description);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft setDescription(String description) {
|
public Draft setDescription(String description) {
|
||||||
return description(description);
|
return description(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Long> demand() {
|
public Map<String, Long> demand() {
|
||||||
return this.<Map<String, Long>>get(supply::demand, Map.class);
|
return this.<Map<String, Long>>get(supply::demand, Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft demand(Map<String, Long> demand) {
|
public Draft demand(Map<String, Long> demand) {
|
||||||
mutate(supply::demand, demand);
|
mutate(supply::demand, demand);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft setDemand(Map<String, Long> demand) {
|
public Draft setDemand(Map<String, Long> demand) {
|
||||||
return demand(demand);
|
return demand(demand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> suppliers() {
|
public List<String> suppliers() {
|
||||||
return this.<List<String>>get(supply::suppliers, List.class);
|
return this.<List<String>>get(supply::suppliers, List.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft suppliers(List<String> suppliers) {
|
public Draft suppliers(List<String> suppliers) {
|
||||||
mutate(supply::suppliers, suppliers);
|
mutate(supply::suppliers, suppliers);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft setSuppliers(List<String> suppliers) {
|
public Draft setSuppliers(List<String> suppliers) {
|
||||||
return suppliers(suppliers);
|
return suppliers(suppliers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> shipments() {
|
public Set<String> shipments() {
|
||||||
return this.<Set<String>>get(supply::shipments, Set.class);
|
return this.<Set<String>>get(supply::shipments, Set.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft shipments(Set<String> shipments) {
|
public Draft shipments(Set<String> shipments) {
|
||||||
mutate(supply::shipments, shipments);
|
mutate(supply::shipments, shipments);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draft setshipments(Set<String> shipments) {
|
public Draft setshipments(Set<String> shipments) {
|
||||||
return shipments(shipments);
|
return shipments(shipments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,17 @@ import net.helenus.mapping.annotation.Transient;
|
||||||
@InheritedTable
|
@InheritedTable
|
||||||
public interface Animal {
|
public interface Animal {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
boolean eatable();
|
boolean eatable();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
boolean warmBlodded();
|
boolean warmBlodded();
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
default Animal me() {
|
default Animal me() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table("cats")
|
@Table("cats")
|
||||||
public interface Cat extends Mammal {
|
public interface Cat extends Mammal {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
@Index(caseSensitive = false)
|
@Index(caseSensitive = false)
|
||||||
String nickname();
|
String nickname();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,73 +5,59 @@ import static net.helenus.core.Query.eq;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class HierarchyTest extends AbstractEmbeddedCassandraTest {
|
public class HierarchyTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Cat cat;
|
static Cat cat;
|
||||||
|
|
||||||
static Pig pig;
|
static Pig pig;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
static Random rnd = new Random();
|
static Random rnd = new Random();
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session =
|
session = Helenus.init(getSession()).showCql().add(Cat.class).add(Pig.class).autoCreateDrop().get();
|
||||||
Helenus.init(getSession()).showCql().add(Cat.class).add(Pig.class).autoCreateDrop().get();
|
cat = Helenus.dsl(Cat.class);
|
||||||
cat = Helenus.dsl(Cat.class);
|
pig = Helenus.dsl(Pig.class);
|
||||||
pig = Helenus.dsl(Pig.class);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(cat);
|
System.out.println(cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() throws TimeoutException {
|
public void testCounter() throws TimeoutException {
|
||||||
|
|
||||||
session
|
session.insert().value(cat::id, rnd.nextInt()).value(cat::nickname, "garfield").value(cat::eatable, false)
|
||||||
.insert()
|
.sync();
|
||||||
.value(cat::id, rnd.nextInt())
|
session.insert().value(pig::id, rnd.nextInt()).value(pig::nickname, "porky").value(pig::eatable, true).sync();
|
||||||
.value(cat::nickname, "garfield")
|
|
||||||
.value(cat::eatable, false)
|
|
||||||
.sync();
|
|
||||||
session
|
|
||||||
.insert()
|
|
||||||
.value(pig::id, rnd.nextInt())
|
|
||||||
.value(pig::nickname, "porky")
|
|
||||||
.value(pig::eatable, true)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
Optional<Cat> animal =
|
Optional<Cat> animal = session.<Cat>select(Cat.class).where(cat::nickname, eq("garfield")).sync().findFirst();
|
||||||
session.<Cat>select(Cat.class).where(cat::nickname, eq("garfield")).sync().findFirst();
|
Assert.assertTrue(animal.isPresent());
|
||||||
Assert.assertTrue(animal.isPresent());
|
Assert.assertTrue(animal.get().warmBlodded());
|
||||||
Assert.assertTrue(animal.get().warmBlodded());
|
Assert.assertFalse(animal.get().eatable());
|
||||||
Assert.assertFalse(animal.get().eatable());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultMethod() throws TimeoutException {
|
public void testDefaultMethod() throws TimeoutException {
|
||||||
session
|
session.insert().value(cat::id, rnd.nextInt()).value(cat::nickname, "garfield").value(cat::eatable, false)
|
||||||
.insert()
|
.sync();
|
||||||
.value(cat::id, rnd.nextInt())
|
Optional<Cat> animal = session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
|
||||||
.value(cat::nickname, "garfield")
|
Assert.assertTrue(animal.isPresent());
|
||||||
.value(cat::eatable, false)
|
|
||||||
.sync();
|
|
||||||
Optional<Cat> animal =
|
|
||||||
session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
|
|
||||||
Assert.assertTrue(animal.isPresent());
|
|
||||||
|
|
||||||
Cat cat = animal.get();
|
Cat cat = animal.get();
|
||||||
Animal itsme = cat.me();
|
Animal itsme = cat.me();
|
||||||
Assert.assertEquals(cat, itsme);
|
Assert.assertEquals(cat, itsme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import net.helenus.mapping.annotation.InheritedTable;
|
||||||
@InheritedTable
|
@InheritedTable
|
||||||
public interface Mammal extends Animal {
|
public interface Mammal extends Animal {
|
||||||
|
|
||||||
default boolean warmBlodded() {
|
default boolean warmBlodded() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,6 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table("pigs")
|
@Table("pigs")
|
||||||
public interface Pig extends Mammal {
|
public interface Pig extends Mammal {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
String nickname();
|
String nickname();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,13 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table("books")
|
@Table("books")
|
||||||
public interface Book {
|
public interface Book {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
long id();
|
long id();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
@Index
|
@Index
|
||||||
String isbn();
|
String isbn();
|
||||||
|
|
||||||
@Column(ordinal = 2)
|
@Column(ordinal = 2)
|
||||||
String author();
|
String author();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,39 +16,35 @@
|
||||||
package net.helenus.test.integration.core.index;
|
package net.helenus.test.integration.core.index;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.Query;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class SecondaryIndexTest extends AbstractEmbeddedCassandraTest {
|
public class SecondaryIndexTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
Book book;
|
Book book;
|
||||||
|
|
||||||
HelenusSession session;
|
HelenusSession session;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeTest() {
|
public void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
||||||
book = Helenus.dsl(Book.class, session.getMetadata());
|
book = Helenus.dsl(Book.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws TimeoutException {
|
public void test() throws TimeoutException {
|
||||||
|
|
||||||
session
|
session.insert().value(book::id, 123L).value(book::isbn, "ABC").value(book::author, "Alex").sync();
|
||||||
.insert()
|
|
||||||
.value(book::id, 123L)
|
|
||||||
.value(book::isbn, "ABC")
|
|
||||||
.value(book::author, "Alex")
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
long actualId =
|
long actualId = session.select(book::id).where(book::isbn, Query.eq("ABC")).sync().findFirst().get()._1;
|
||||||
session.select(book::id).where(book::isbn, Query.eq("ABC")).sync().findFirst().get()._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(123L, actualId);
|
Assert.assertEquals(123L, actualId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package net.helenus.test.integration.core.prepared;
|
package net.helenus.test.integration.core.prepared;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import net.helenus.core.annotation.Cacheable;
|
import net.helenus.core.annotation.Cacheable;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
@ -24,13 +25,13 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Cacheable
|
@Cacheable
|
||||||
public interface Car {
|
public interface Car {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
String make();
|
String make();
|
||||||
|
|
||||||
@PartitionKey(ordinal = 1)
|
@PartitionKey(ordinal = 1)
|
||||||
String model();
|
String model();
|
||||||
|
|
||||||
int year();
|
int year();
|
||||||
|
|
||||||
BigDecimal price();
|
BigDecimal price();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.prepared;
|
package net.helenus.test.integration.core.prepared;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.Query;
|
import net.helenus.core.Query;
|
||||||
|
@ -24,115 +30,86 @@ import net.helenus.core.operation.PreparedOperation;
|
||||||
import net.helenus.core.operation.PreparedStreamOperation;
|
import net.helenus.core.operation.PreparedStreamOperation;
|
||||||
import net.helenus.support.Fun;
|
import net.helenus.support.Fun;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class PreparedStatementTest extends AbstractEmbeddedCassandraTest {
|
public class PreparedStatementTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Car car;
|
static Car car;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
static PreparedOperation<ResultSet> insertOp;
|
static PreparedOperation<ResultSet> insertOp;
|
||||||
|
|
||||||
static PreparedOperation<ResultSet> updateOp;
|
static PreparedOperation<ResultSet> updateOp;
|
||||||
|
|
||||||
static PreparedStreamOperation<Car> selectOp;
|
static PreparedStreamOperation<Car> selectOp;
|
||||||
|
|
||||||
static PreparedStreamOperation<Fun.Tuple1<BigDecimal>> selectPriceOp;
|
static PreparedStreamOperation<Fun.Tuple1<BigDecimal>> selectPriceOp;
|
||||||
|
|
||||||
static PreparedOperation<ResultSet> deleteOp;
|
static PreparedOperation<ResultSet> deleteOp;
|
||||||
|
|
||||||
static PreparedOperation<Long> countOp;
|
static PreparedOperation<Long> countOp;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
|
|
||||||
session = Helenus.init(getSession()).showCql().add(Car.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Car.class).autoCreateDrop().get();
|
||||||
car = Helenus.dsl(Car.class, session.getMetadata());
|
car = Helenus.dsl(Car.class, session.getMetadata());
|
||||||
|
|
||||||
insertOp =
|
insertOp = session.<ResultSet>insert().value(car::make, Query.marker()).value(car::model, Query.marker())
|
||||||
session
|
.value(car::year, 2004).prepare();
|
||||||
.<ResultSet>insert()
|
|
||||||
.value(car::make, Query.marker())
|
|
||||||
.value(car::model, Query.marker())
|
|
||||||
.value(car::year, 2004)
|
|
||||||
.prepare();
|
|
||||||
|
|
||||||
updateOp =
|
updateOp = session.update().set(car::price, Query.marker()).where(car::make, Query.eq(Query.marker()))
|
||||||
session
|
.and(car::model, Query.eq(Query.marker())).prepare();
|
||||||
.update()
|
|
||||||
.set(car::price, Query.marker())
|
|
||||||
.where(car::make, Query.eq(Query.marker()))
|
|
||||||
.and(car::model, Query.eq(Query.marker()))
|
|
||||||
.prepare();
|
|
||||||
|
|
||||||
selectOp =
|
selectOp = session.<Car>select(car).where(car::make, Query.eq(Query.marker()))
|
||||||
session
|
.and(car::model, Query.eq(Query.marker())).prepare();
|
||||||
.<Car>select(car)
|
|
||||||
.where(car::make, Query.eq(Query.marker()))
|
|
||||||
.and(car::model, Query.eq(Query.marker()))
|
|
||||||
.prepare();
|
|
||||||
|
|
||||||
selectPriceOp =
|
selectPriceOp = session.select(car::price).where(car::make, Query.eq(Query.marker()))
|
||||||
session
|
.and(car::model, Query.eq(Query.marker())).prepare();
|
||||||
.select(car::price)
|
|
||||||
.where(car::make, Query.eq(Query.marker()))
|
|
||||||
.and(car::model, Query.eq(Query.marker()))
|
|
||||||
.prepare();
|
|
||||||
|
|
||||||
deleteOp =
|
deleteOp = session.delete().where(car::make, Query.eq(Query.marker())).and(car::model, Query.eq(Query.marker()))
|
||||||
session
|
.prepare();
|
||||||
.delete()
|
|
||||||
.where(car::make, Query.eq(Query.marker()))
|
|
||||||
.and(car::model, Query.eq(Query.marker()))
|
|
||||||
.prepare();
|
|
||||||
|
|
||||||
countOp =
|
countOp = session.count().where(car::make, Query.eq(Query.marker())).and(car::model, Query.eq(Query.marker()))
|
||||||
session
|
.prepare();
|
||||||
.count()
|
}
|
||||||
.where(car::make, Query.eq(Query.marker()))
|
|
||||||
.and(car::model, Query.eq(Query.marker()))
|
|
||||||
.prepare();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(car);
|
System.out.println(car);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCRUID() throws Exception {
|
public void testCRUID() throws Exception {
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
insertOp.bind("Nissan", "350Z").sync();
|
insertOp.bind("Nissan", "350Z").sync();
|
||||||
|
|
||||||
// SELECT
|
// SELECT
|
||||||
|
|
||||||
Car actual = selectOp.bind("Nissan", "350Z").sync().findFirst().get();
|
Car actual = selectOp.bind("Nissan", "350Z").sync().findFirst().get();
|
||||||
Assert.assertEquals("Nissan", actual.make());
|
Assert.assertEquals("Nissan", actual.make());
|
||||||
Assert.assertEquals("350Z", actual.model());
|
Assert.assertEquals("350Z", actual.model());
|
||||||
Assert.assertEquals(2004, actual.year());
|
Assert.assertEquals(2004, actual.year());
|
||||||
Assert.assertNull(actual.price());
|
Assert.assertNull(actual.price());
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
updateOp.bind(BigDecimal.valueOf(10000.0), "Nissan", "350Z").sync();
|
updateOp.bind(BigDecimal.valueOf(10000.0), "Nissan", "350Z").sync();
|
||||||
|
|
||||||
BigDecimal price = selectPriceOp.bind("Nissan", "350Z").sync().findFirst().get()._1;
|
BigDecimal price = selectPriceOp.bind("Nissan", "350Z").sync().findFirst().get()._1;
|
||||||
|
|
||||||
Assert.assertEquals(BigDecimal.valueOf(10000.0), price);
|
Assert.assertEquals(BigDecimal.valueOf(10000.0), price);
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
Long cnt = countOp.bind("Nissan", "350Z").sync();
|
Long cnt = countOp.bind("Nissan", "350Z").sync();
|
||||||
Assert.assertEquals(Long.valueOf(1), cnt);
|
Assert.assertEquals(Long.valueOf(1), cnt);
|
||||||
|
|
||||||
deleteOp.bind("Nissan", "350Z").sync();
|
deleteOp.bind("Nissan", "350Z").sync();
|
||||||
|
|
||||||
cnt = countOp.bind("Nissan", "350Z").sync();
|
cnt = countOp.bind("Nissan", "350Z").sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,48 +18,49 @@ package net.helenus.test.integration.core.simple;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.operation.InsertOperation;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.operation.InsertOperation;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class InsertPartialTest extends AbstractEmbeddedCassandraTest {
|
public class InsertPartialTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
static User user;
|
static User user;
|
||||||
static Random rnd = new Random();
|
static Random rnd = new Random();
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTests() {
|
public static void beforeTests() {
|
||||||
session = Helenus.init(getSession()).showCql().add(User.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(User.class).autoCreateDrop().get();
|
||||||
user = Helenus.dsl(User.class);
|
user = Helenus.dsl(User.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPartialInsert() throws Exception {
|
public void testPartialInsert() throws Exception {
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
Long id = rnd.nextLong();
|
Long id = rnd.nextLong();
|
||||||
map.put("id", id);
|
map.put("id", id);
|
||||||
map.put("age", 5);
|
map.put("age", 5);
|
||||||
InsertOperation<User> insert = session.<User>insert(Helenus.map(User.class, map));
|
InsertOperation<User> insert = session.<User>insert(Helenus.map(User.class, map));
|
||||||
String cql =
|
String cql = "INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5) IF NOT EXISTS;";
|
||||||
"INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5) IF NOT EXISTS;";
|
Assert.assertEquals(cql, insert.cql());
|
||||||
Assert.assertEquals(cql, insert.cql());
|
insert.sync();
|
||||||
insert.sync();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPartialUpsert() throws Exception {
|
public void testPartialUpsert() throws Exception {
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
Long id = rnd.nextLong();
|
Long id = rnd.nextLong();
|
||||||
map.put("id", id);
|
map.put("id", id);
|
||||||
map.put("age", 5);
|
map.put("age", 5);
|
||||||
InsertOperation upsert = session.upsert(Helenus.map(User.class, map));
|
InsertOperation upsert = session.upsert(Helenus.map(User.class, map));
|
||||||
String cql = "INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5);";
|
String cql = "INSERT INTO simple_users (id,age) VALUES (" + id.toString() + ",5);";
|
||||||
Assert.assertEquals(cql, upsert.cql());
|
Assert.assertEquals(cql, upsert.cql());
|
||||||
upsert.sync();
|
upsert.sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,29 +16,25 @@
|
||||||
package net.helenus.test.integration.core.simple;
|
package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import net.helenus.mapping.annotation.ClusteringColumn;
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.*;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
|
||||||
import net.helenus.mapping.annotation.StaticColumn;
|
|
||||||
import net.helenus.mapping.annotation.Table;
|
|
||||||
import net.helenus.mapping.annotation.Types;
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Message {
|
public interface Message {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
@ClusteringColumn
|
@ClusteringColumn
|
||||||
@Types.Timeuuid
|
@Types.Timeuuid
|
||||||
Date timestamp();
|
Date timestamp();
|
||||||
|
|
||||||
@StaticColumn(forceQuote = true)
|
@StaticColumn(forceQuote = true)
|
||||||
String from();
|
String from();
|
||||||
|
|
||||||
@Column(forceQuote = true)
|
@Column(forceQuote = true)
|
||||||
String to();
|
String to();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
String message();
|
String message();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,242 +17,173 @@ package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import java.util.Optional;
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.Operator;
|
import net.helenus.core.Operator;
|
||||||
import net.helenus.core.operation.UpdateOperation;
|
import net.helenus.core.operation.UpdateOperation;
|
||||||
import net.helenus.support.Fun;
|
import net.helenus.support.Fun;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static User user;
|
static User user;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(User.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(User.class).autoCreateDrop().get();
|
||||||
user = Helenus.dsl(User.class, session.getMetadata());
|
user = Helenus.dsl(User.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UserImpl implements User {
|
@Test
|
||||||
|
public void testCruid() throws Exception {
|
||||||
|
|
||||||
Long id;
|
UserImpl newUser = new UserImpl();
|
||||||
String name;
|
newUser.id = 100L;
|
||||||
Integer age;
|
newUser.name = "alex";
|
||||||
UserType type;
|
newUser.age = 34;
|
||||||
|
newUser.type = UserType.USER;
|
||||||
|
|
||||||
@Override
|
// CREATE
|
||||||
public Long id() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
session.upsert(newUser).sync();
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// READ
|
||||||
public Integer age() {
|
|
||||||
return age;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// select row and map to entity
|
||||||
public UserType type() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
User actual = session.selectAll(User.class).mapTo(User.class).where(user::id, eq(100L)).sync().findFirst()
|
||||||
public void testCruid() throws Exception {
|
.get();
|
||||||
|
assertUsers(newUser, actual);
|
||||||
|
|
||||||
UserImpl newUser = new UserImpl();
|
// select as object
|
||||||
newUser.id = 100L;
|
|
||||||
newUser.name = "alex";
|
|
||||||
newUser.age = 34;
|
|
||||||
newUser.type = UserType.USER;
|
|
||||||
|
|
||||||
// CREATE
|
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||||
|
assertUsers(newUser, actual);
|
||||||
|
|
||||||
session.upsert(newUser).sync();
|
// select by columns
|
||||||
|
|
||||||
// READ
|
actual = session.select().column(user::id).column(user::name).column(user::age).column(user::type)
|
||||||
|
.mapTo(User.class).where(user::id, eq(100L)).sync().findFirst().get();
|
||||||
|
assertUsers(newUser, actual);
|
||||||
|
|
||||||
// select row and map to entity
|
// select by columns
|
||||||
|
|
||||||
User actual =
|
actual = session.select(User.class).mapTo(User.class).where(user::id, eq(100L)).sync().findFirst().get();
|
||||||
session
|
assertUsers(newUser, actual);
|
||||||
.selectAll(User.class)
|
|
||||||
.mapTo(User.class)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
assertUsers(newUser, actual);
|
|
||||||
|
|
||||||
// select as object
|
// select as object and mapTo
|
||||||
|
|
||||||
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
actual = session.select(user::id, user::name, user::age, user::type).mapTo(User.class).where(user::id, eq(100L))
|
||||||
assertUsers(newUser, actual);
|
.sync().findFirst().get();
|
||||||
|
assertUsers(newUser, actual);
|
||||||
|
|
||||||
// select by columns
|
// select single column
|
||||||
|
|
||||||
actual =
|
String name = session.select(user::name).where(user::id, eq(100L)).sync().findFirst().get()._1;
|
||||||
session
|
|
||||||
.select()
|
|
||||||
.column(user::id)
|
|
||||||
.column(user::name)
|
|
||||||
.column(user::age)
|
|
||||||
.column(user::type)
|
|
||||||
.mapTo(User.class)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
assertUsers(newUser, actual);
|
|
||||||
|
|
||||||
// select by columns
|
Assert.assertEquals(newUser.name(), name);
|
||||||
|
|
||||||
actual =
|
// select single column in array tuple
|
||||||
session
|
|
||||||
.select(User.class)
|
|
||||||
.mapTo(User.class)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
assertUsers(newUser, actual);
|
|
||||||
|
|
||||||
// select as object and mapTo
|
name = (String) session.select().column(user::name).where(user::id, eq(100L)).sync().findFirst().get()._a[0];
|
||||||
|
|
||||||
actual =
|
Assert.assertEquals(newUser.name(), name);
|
||||||
session
|
|
||||||
.select(user::id, user::name, user::age, user::type)
|
|
||||||
.mapTo(User.class)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
assertUsers(newUser, actual);
|
|
||||||
|
|
||||||
// select single column
|
// UPDATE
|
||||||
|
|
||||||
String name = session.select(user::name).where(user::id, eq(100L)).sync().findFirst().get()._1;
|
session.update(user::name, "albert").set(user::age, 35).where(user::id, Operator.EQ, 100L).sync();
|
||||||
|
|
||||||
Assert.assertEquals(newUser.name(), name);
|
long cnt = session.count(user).where(user::id, Operator.EQ, 100L).sync();
|
||||||
|
Assert.assertEquals(1L, cnt);
|
||||||
|
|
||||||
// select single column in array tuple
|
name = session.select(user::name).where(user::id, Operator.EQ, 100L).map(t -> "_" + t._1).sync().findFirst()
|
||||||
|
.get();
|
||||||
|
|
||||||
name =
|
Assert.assertEquals("_albert", name);
|
||||||
(String)
|
|
||||||
session
|
|
||||||
.select()
|
|
||||||
.column(user::name)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._a[0];
|
|
||||||
|
|
||||||
Assert.assertEquals(newUser.name(), name);
|
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||||
|
|
||||||
// UPDATE
|
Assert.assertEquals(Long.valueOf(100L), u2.id());
|
||||||
|
Assert.assertEquals("albert", u2.name());
|
||||||
|
Assert.assertEquals(Integer.valueOf(35), u2.age());
|
||||||
|
|
||||||
session
|
//
|
||||||
.update(user::name, "albert")
|
User greg = session.<User>insert(user).value(user::name, "greg").value(user::age, 44)
|
||||||
.set(user::age, 35)
|
.value(user::type, UserType.USER).value(user::id, 1234L).sync();
|
||||||
.where(user::id, Operator.EQ, 100L)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
long cnt = session.count(user).where(user::id, Operator.EQ, 100L).sync();
|
Optional<User> maybeGreg = session.<User>select(user).where(user::id, eq(1234L)).single().sync();
|
||||||
Assert.assertEquals(1L, cnt);
|
|
||||||
|
|
||||||
name =
|
// INSERT
|
||||||
session
|
|
||||||
.select(user::name)
|
|
||||||
.where(user::id, Operator.EQ, 100L)
|
|
||||||
.map(t -> "_" + t._1)
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
|
|
||||||
Assert.assertEquals("_albert", name);
|
session.update().set(user::name, null).set(user::age, null).set(user::type, null).where(user::id, eq(100L))
|
||||||
|
.zipkinContext(null).sync();
|
||||||
|
|
||||||
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
Fun.Tuple3<String, Integer, UserType> tuple = session.select(user::name, user::age, user::type)
|
||||||
|
.where(user::id, eq(100L)).sync().findFirst().get();
|
||||||
|
|
||||||
Assert.assertEquals(Long.valueOf(100L), u2.id());
|
Assert.assertNull(tuple._1);
|
||||||
Assert.assertEquals("albert", u2.name());
|
Assert.assertNull(tuple._2);
|
||||||
Assert.assertEquals(Integer.valueOf(35), u2.age());
|
Assert.assertNull(tuple._3);
|
||||||
|
|
||||||
//
|
// DELETE
|
||||||
User greg =
|
|
||||||
session
|
|
||||||
.<User>insert(user)
|
|
||||||
.value(user::name, "greg")
|
|
||||||
.value(user::age, 44)
|
|
||||||
.value(user::type, UserType.USER)
|
|
||||||
.value(user::id, 1234L)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
Optional<User> maybeGreg =
|
session.delete(user).where(user::id, eq(100L)).sync();
|
||||||
session.<User>select(user).where(user::id, eq(1234L)).single().sync();
|
|
||||||
|
|
||||||
// INSERT
|
cnt = session.select().count().where(user::id, eq(100L)).sync();
|
||||||
|
Assert.assertEquals(0L, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
session
|
public void testZipkin() throws TimeoutException {
|
||||||
.update()
|
session.update().set(user::name, null).set(user::age, null).set(user::type, null).where(user::id, eq(100L))
|
||||||
.set(user::name, null)
|
.zipkinContext(null).sync();
|
||||||
.set(user::age, null)
|
|
||||||
.set(user::type, null)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.zipkinContext(null)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
Fun.Tuple3<String, Integer, UserType> tuple =
|
UpdateOperation<ResultSet> update = session.update();
|
||||||
session
|
update.set(user::name, null).zipkinContext(null).sync();
|
||||||
.select(user::name, user::age, user::type)
|
}
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get();
|
|
||||||
|
|
||||||
Assert.assertNull(tuple._1);
|
private void assertUsers(User expected, User actual) {
|
||||||
Assert.assertNull(tuple._2);
|
Assert.assertEquals(expected.id(), actual.id());
|
||||||
Assert.assertNull(tuple._3);
|
Assert.assertEquals(expected.name(), actual.name());
|
||||||
|
Assert.assertEquals(expected.age(), actual.age());
|
||||||
|
Assert.assertEquals(expected.type(), actual.type());
|
||||||
|
}
|
||||||
|
|
||||||
// DELETE
|
public static class UserImpl implements User {
|
||||||
|
|
||||||
session.delete(user).where(user::id, eq(100L)).sync();
|
Long id;
|
||||||
|
String name;
|
||||||
|
Integer age;
|
||||||
|
UserType type;
|
||||||
|
|
||||||
cnt = session.select().count().where(user::id, eq(100L)).sync();
|
@Override
|
||||||
Assert.assertEquals(0L, cnt);
|
public Long id() {
|
||||||
}
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
public void testZipkin() throws TimeoutException {
|
@Override
|
||||||
session
|
public String name() {
|
||||||
.update()
|
return name;
|
||||||
.set(user::name, null)
|
}
|
||||||
.set(user::age, null)
|
|
||||||
.set(user::type, null)
|
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.zipkinContext(null)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
UpdateOperation<ResultSet> update = session.update();
|
@Override
|
||||||
update.set(user::name, null).zipkinContext(null).sync();
|
public Integer age() {
|
||||||
}
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
private void assertUsers(User expected, User actual) {
|
@Override
|
||||||
Assert.assertEquals(expected.id(), actual.id());
|
public UserType type() {
|
||||||
Assert.assertEquals(expected.name(), actual.name());
|
return type;
|
||||||
Assert.assertEquals(expected.age(), actual.age());
|
}
|
||||||
Assert.assertEquals(expected.type(), actual.type());
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,152 +19,129 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.Query;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
|
public class StaticColumnTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
static Message message;
|
static Message message;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session =
|
session = Helenus.init(getSession()).showCql().addPackage(Message.class.getPackage().getName()).autoCreateDrop()
|
||||||
Helenus.init(getSession())
|
.get();
|
||||||
.showCql()
|
message = Helenus.dsl(Message.class, session.getMetadata());
|
||||||
.addPackage(Message.class.getPackage().getName())
|
}
|
||||||
.autoCreateDrop()
|
|
||||||
.get();
|
|
||||||
message = Helenus.dsl(Message.class, session.getMetadata());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MessageImpl implements Message {
|
@Test
|
||||||
|
public void testCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id;
|
MessageImpl msg = new MessageImpl();
|
||||||
Date timestamp;
|
msg.id = 123;
|
||||||
String from;
|
msg.timestamp = new Date();
|
||||||
String to;
|
msg.from = "Alex";
|
||||||
String msg;
|
msg.to = "Bob";
|
||||||
|
msg.msg = "hi";
|
||||||
|
|
||||||
@Override
|
// CREATE
|
||||||
public int id() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
session.insert(msg).sync();
|
||||||
public Date timestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
msg.id = 123;
|
||||||
public String from() {
|
msg.to = "Craig";
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
session.insert(msg).sync();
|
||||||
public String to() {
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// READ
|
||||||
public String message() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
List<Message> actual = session.<Message>select(message).where(message::id, Query.eq(123)).sync()
|
||||||
public void testCRUID() throws TimeoutException {
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
MessageImpl msg = new MessageImpl();
|
Assert.assertEquals(2, actual.size());
|
||||||
msg.id = 123;
|
|
||||||
msg.timestamp = new Date();
|
|
||||||
msg.from = "Alex";
|
|
||||||
msg.to = "Bob";
|
|
||||||
msg.msg = "hi";
|
|
||||||
|
|
||||||
// CREATE
|
Message toCraig = actual.stream().filter(m -> m.to().equals("Craig")).findFirst().get();
|
||||||
|
assertMessages(msg, toCraig);
|
||||||
|
|
||||||
session.insert(msg).sync();
|
// UPDATE
|
||||||
|
|
||||||
msg.id = 123;
|
session.update().set(message::from, "Albert").where(message::id, Query.eq(123))
|
||||||
msg.to = "Craig";
|
.onlyIf(message::from, Query.eq("Alex")).sync();
|
||||||
|
|
||||||
session.insert(msg).sync();
|
long cnt = session.select(message::from).where(message::id, Query.eq(123)).sync()
|
||||||
|
.filter(t -> t._1.equals("Albert")).count();
|
||||||
|
|
||||||
// READ
|
Assert.assertEquals(2, cnt);
|
||||||
|
|
||||||
List<Message> actual =
|
// INSERT
|
||||||
session
|
|
||||||
.<Message>select(message)
|
|
||||||
.where(message::id, Query.eq(123))
|
|
||||||
.sync()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
Assert.assertEquals(2, actual.size());
|
session.update().set(message::from, null).where(message::id, Query.eq(123)).sync();
|
||||||
|
|
||||||
Message toCraig = actual.stream().filter(m -> m.to().equals("Craig")).findFirst().get();
|
session.select(message::from).where(message::id, Query.eq(123)).sync().map(t -> t._1)
|
||||||
assertMessages(msg, toCraig);
|
.forEach(Assert::assertNull);
|
||||||
|
|
||||||
// UPDATE
|
session.update().set(message::from, "Alex").where(message::id, Query.eq(123))
|
||||||
|
.onlyIf(message::from, Query.eq(null)).sync();
|
||||||
|
|
||||||
session
|
// DELETE
|
||||||
.update()
|
|
||||||
.set(message::from, "Albert")
|
|
||||||
.where(message::id, Query.eq(123))
|
|
||||||
.onlyIf(message::from, Query.eq("Alex"))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
long cnt =
|
session.delete().where(message::id, Query.eq(123)).sync();
|
||||||
session
|
|
||||||
.select(message::from)
|
|
||||||
.where(message::id, Query.eq(123))
|
|
||||||
.sync()
|
|
||||||
.filter(t -> t._1.equals("Albert"))
|
|
||||||
.count();
|
|
||||||
|
|
||||||
Assert.assertEquals(2, cnt);
|
cnt = session.count().where(message::id, Query.eq(123)).sync();
|
||||||
|
Assert.assertEquals(0, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
// INSERT
|
private void assertMessages(Message expected, Message actual) {
|
||||||
|
Assert.assertEquals(expected.id(), actual.id());
|
||||||
|
Assert.assertEquals(expected.from(), actual.from());
|
||||||
|
Assert.assertEquals(expected.timestamp(), actual.timestamp());
|
||||||
|
Assert.assertEquals(expected.to(), actual.to());
|
||||||
|
Assert.assertEquals(expected.message(), actual.message());
|
||||||
|
}
|
||||||
|
|
||||||
session.update().set(message::from, null).where(message::id, Query.eq(123)).sync();
|
private static class MessageImpl implements Message {
|
||||||
|
|
||||||
session
|
int id;
|
||||||
.select(message::from)
|
Date timestamp;
|
||||||
.where(message::id, Query.eq(123))
|
String from;
|
||||||
.sync()
|
String to;
|
||||||
.map(t -> t._1)
|
String msg;
|
||||||
.forEach(Assert::assertNull);
|
|
||||||
|
|
||||||
session
|
@Override
|
||||||
.update()
|
public int id() {
|
||||||
.set(message::from, "Alex")
|
return id;
|
||||||
.where(message::id, Query.eq(123))
|
}
|
||||||
.onlyIf(message::from, Query.eq(null))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
// DELETE
|
@Override
|
||||||
|
public Date timestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
session.delete().where(message::id, Query.eq(123)).sync();
|
@Override
|
||||||
|
public String from() {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
cnt = session.count().where(message::id, Query.eq(123)).sync();
|
@Override
|
||||||
Assert.assertEquals(0, cnt);
|
public String to() {
|
||||||
}
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
private void assertMessages(Message expected, Message actual) {
|
@Override
|
||||||
Assert.assertEquals(expected.id(), actual.id());
|
public String message() {
|
||||||
Assert.assertEquals(expected.from(), actual.from());
|
return msg;
|
||||||
Assert.assertEquals(expected.timestamp(), actual.timestamp());
|
}
|
||||||
Assert.assertEquals(expected.to(), actual.to());
|
}
|
||||||
Assert.assertEquals(expected.message(), actual.message());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.simple;
|
package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
import net.helenus.core.annotation.Cacheable;
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
@ -23,14 +22,14 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table("simple_users")
|
@Table("simple_users")
|
||||||
public interface User {
|
public interface User {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
Long id();
|
Long id();
|
||||||
|
|
||||||
@Username
|
@Username
|
||||||
@Column("override_name")
|
@Column("override_name")
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
Integer age();
|
Integer age();
|
||||||
|
|
||||||
UserType type();
|
UserType type();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,5 @@
|
||||||
package net.helenus.test.integration.core.simple;
|
package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
public enum UserType {
|
public enum UserType {
|
||||||
USER,
|
USER, ADMIN;
|
||||||
ADMIN;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.simple;
|
package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import net.helenus.mapping.annotation.Constraints;
|
import net.helenus.mapping.annotation.Constraints;
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
@Constraints.LowerCase
|
@Constraints.LowerCase
|
||||||
public @interface Username {}
|
public @interface Username {
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package net.helenus.test.integration.core.tuple;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType;
|
import com.datastax.driver.core.DataType;
|
||||||
import com.datastax.driver.core.TupleValue;
|
import com.datastax.driver.core.TupleValue;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
@ -25,12 +26,12 @@ import net.helenus.mapping.annotation.Types;
|
||||||
@Table
|
@Table
|
||||||
public interface Album {
|
public interface Album {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 1)
|
@PartitionKey(ordinal = 1)
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
AlbumInformation info();
|
AlbumInformation info();
|
||||||
|
|
||||||
@Types.Tuple({DataType.Name.TEXT, DataType.Name.TEXT})
|
@Types.Tuple({DataType.Name.TEXT, DataType.Name.TEXT})
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
TupleValue infoNoMapping();
|
TupleValue infoNoMapping();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ import net.helenus.mapping.annotation.Tuple;
|
||||||
@Tuple
|
@Tuple
|
||||||
public interface AlbumInformation {
|
public interface AlbumInformation {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
String about();
|
String about();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
String place();
|
String place();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,21 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.tuple;
|
package net.helenus.test.integration.core.tuple;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class DslTest extends AbstractEmbeddedCassandraTest {
|
public class DslTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDslBeforeSessionInit() {
|
public void testDslBeforeSessionInit() {
|
||||||
Assert.assertNotNull(Helenus.dsl(Album.class));
|
Assert.assertNotNull(Helenus.dsl(Album.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSessionInitAddingDslProxy() {
|
public void testSessionInitAddingDslProxy() {
|
||||||
Assert.assertNotNull(Helenus.init(getSession()).showCql().add(Helenus.dsl(Album.class)));
|
Assert.assertNotNull(Helenus.init(getSession()).showCql().add(Helenus.dsl(Album.class)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,129 +16,108 @@
|
||||||
package net.helenus.test.integration.core.tuple;
|
package net.helenus.test.integration.core.tuple;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.Query;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
|
public class InnerTupleTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static PhotoAlbum photoAlbum;
|
static PhotoAlbum photoAlbum;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(PhotoAlbum.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(PhotoAlbum.class).autoCreateDrop().get();
|
||||||
photoAlbum = Helenus.dsl(PhotoAlbum.class, session.getMetadata());
|
photoAlbum = Helenus.dsl(PhotoAlbum.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(photoAlbum);
|
System.out.println(photoAlbum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCruid() throws TimeoutException {
|
public void testCruid() throws TimeoutException {
|
||||||
|
|
||||||
Photo photo =
|
Photo photo = new Photo() {
|
||||||
new Photo() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] blob() {
|
public byte[] blob() {
|
||||||
return "jpeg".getBytes();
|
return "jpeg".getBytes();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PhotoFolder folder =
|
PhotoFolder folder = new PhotoFolder() {
|
||||||
new PhotoFolder() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "first";
|
return "first";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Photo photo() {
|
public Photo photo() {
|
||||||
return photo;
|
return photo;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CREATE (C)
|
// CREATE (C)
|
||||||
|
|
||||||
session.insert().value(photoAlbum::id, 123).value(photoAlbum::folder, folder).sync();
|
session.insert().value(photoAlbum::id, 123).value(photoAlbum::folder, folder).sync();
|
||||||
|
|
||||||
// READ (R)
|
// READ (R)
|
||||||
|
|
||||||
PhotoFolder actual =
|
PhotoFolder actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst()
|
||||||
session
|
.get()._1;
|
||||||
.select(photoAlbum::folder)
|
|
||||||
.where(photoAlbum::id, Query.eq(123))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(folder.name(), actual.name());
|
Assert.assertEquals(folder.name(), actual.name());
|
||||||
|
|
||||||
// UPDATE (U)
|
// UPDATE (U)
|
||||||
|
|
||||||
// unfortunately this is not working right now in Cassandra, can not update a single column in tuple :(
|
// unfortunately this is not working right now in Cassandra, can not update a
|
||||||
//session.update()
|
// single column in tuple :(
|
||||||
// .set(photoAlbum.folder().photo()::blob, "Helenus".getBytes())
|
// session.update()
|
||||||
// .where(photoAlbum::id, eq(123))
|
// .set(photoAlbum.folder().photo()::blob, "Helenus".getBytes())
|
||||||
// .sync();
|
// .where(photoAlbum::id, eq(123))
|
||||||
|
// .sync();
|
||||||
|
|
||||||
PhotoFolder expected =
|
PhotoFolder expected = new PhotoFolder() {
|
||||||
new PhotoFolder() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "seconds";
|
return "seconds";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Photo photo() {
|
public Photo photo() {
|
||||||
return photo;
|
return photo;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
session.update().set(photoAlbum::folder, expected).where(photoAlbum::id, Query.eq(123)).sync();
|
session.update().set(photoAlbum::folder, expected).where(photoAlbum::id, Query.eq(123)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst().get()._1;
|
||||||
session
|
|
||||||
.select(photoAlbum::folder)
|
|
||||||
.where(photoAlbum::id, Query.eq(123))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(expected.name(), actual.name());
|
Assert.assertEquals(expected.name(), actual.name());
|
||||||
|
|
||||||
// INSERT (I)
|
// INSERT (I)
|
||||||
// let's insert null ;)
|
// let's insert null ;)
|
||||||
|
|
||||||
session.update().set(photoAlbum::folder, null).where(photoAlbum::id, Query.eq(123)).sync();
|
session.update().set(photoAlbum::folder, null).where(photoAlbum::id, Query.eq(123)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().findFirst().get()._1;
|
||||||
session
|
Assert.assertNull(actual);
|
||||||
.select(photoAlbum::folder)
|
|
||||||
.where(photoAlbum::id, Query.eq(123))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertNull(actual);
|
|
||||||
|
|
||||||
// DELETE (D)
|
// DELETE (D)
|
||||||
session.delete().where(photoAlbum::id, Query.eq(123)).sync();
|
session.delete().where(photoAlbum::id, Query.eq(123)).sync();
|
||||||
|
|
||||||
long cnt =
|
long cnt = session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().count();
|
||||||
session.select(photoAlbum::folder).where(photoAlbum::id, Query.eq(123)).sync().count();
|
Assert.assertEquals(0, cnt);
|
||||||
Assert.assertEquals(0, cnt);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,5 @@ import net.helenus.mapping.annotation.Tuple;
|
||||||
@Tuple
|
@Tuple
|
||||||
public interface Photo {
|
public interface Photo {
|
||||||
|
|
||||||
byte[] blob();
|
byte[] blob();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table
|
@Table
|
||||||
public interface PhotoAlbum {
|
public interface PhotoAlbum {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
PhotoFolder folder();
|
PhotoFolder folder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ import net.helenus.mapping.annotation.Tuple;
|
||||||
@Tuple
|
@Tuple
|
||||||
public interface PhotoFolder {
|
public interface PhotoFolder {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
Photo photo();
|
Photo photo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,157 +17,155 @@ package net.helenus.test.integration.core.tuple;
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType;
|
|
||||||
import com.datastax.driver.core.TupleType;
|
|
||||||
import com.datastax.driver.core.TupleValue;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.DataType;
|
||||||
|
import com.datastax.driver.core.TupleType;
|
||||||
|
import com.datastax.driver.core.TupleValue;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class TupleTest extends AbstractEmbeddedCassandraTest {
|
public class TupleTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Album album;
|
static Album album;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
Helenus.clearDslCache();
|
Helenus.clearDslCache();
|
||||||
session = Helenus.init(getSession()).showCql().add(Album.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Album.class).autoCreateDrop().get();
|
||||||
album = Helenus.dsl(Album.class, session.getMetadata());
|
album = Helenus.dsl(Album.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(album);
|
System.out.println(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCruid() throws TimeoutException {
|
public void testCruid() throws TimeoutException {
|
||||||
|
|
||||||
AlbumInformation info =
|
AlbumInformation info = new AlbumInformation() {
|
||||||
new AlbumInformation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String about() {
|
public String about() {
|
||||||
return "Cassandra";
|
return "Cassandra";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String place() {
|
public String place() {
|
||||||
return "San Jose";
|
return "San Jose";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CREATE (C)
|
// CREATE (C)
|
||||||
|
|
||||||
session.insert().value(album::id, 123).value(album::info, info).sync();
|
session.insert().value(album::id, 123).value(album::info, info).sync();
|
||||||
|
|
||||||
// READ (R)
|
// READ (R)
|
||||||
|
|
||||||
AlbumInformation actual =
|
AlbumInformation actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
||||||
session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(info.about(), actual.about());
|
Assert.assertEquals(info.about(), actual.about());
|
||||||
Assert.assertEquals(info.place(), actual.place());
|
Assert.assertEquals(info.place(), actual.place());
|
||||||
|
|
||||||
// UPDATE (U)
|
// UPDATE (U)
|
||||||
|
|
||||||
// unfortunately this is not working right now in Cassandra, can not update a single column in tuple :(
|
// unfortunately this is not working right now in Cassandra, can not update a
|
||||||
//session.update()
|
// single column in tuple :(
|
||||||
// .set(album.info()::about, "Helenus")
|
// session.update()
|
||||||
// .where(album::id, eq(123))
|
// .set(album.info()::about, "Helenus")
|
||||||
// .sync();
|
// .where(album::id, eq(123))
|
||||||
|
// .sync();
|
||||||
|
|
||||||
AlbumInformation expected =
|
AlbumInformation expected = new AlbumInformation() {
|
||||||
new AlbumInformation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String about() {
|
public String about() {
|
||||||
return "Helenus";
|
return "Helenus";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String place() {
|
public String place() {
|
||||||
return "Santa Cruz";
|
return "Santa Cruz";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
session.update().set(album::info, expected).where(album::id, eq(123)).sync();
|
session.update().set(album::info, expected).where(album::id, eq(123)).sync();
|
||||||
|
|
||||||
actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
||||||
|
|
||||||
Assert.assertEquals(expected.about(), actual.about());
|
Assert.assertEquals(expected.about(), actual.about());
|
||||||
Assert.assertEquals(expected.place(), actual.place());
|
Assert.assertEquals(expected.place(), actual.place());
|
||||||
|
|
||||||
// INSERT (I)
|
// INSERT (I)
|
||||||
// let's insert null ;)
|
// let's insert null ;)
|
||||||
|
|
||||||
session.update().set(album::info, null).where(album::id, eq(123)).sync();
|
session.update().set(album::info, null).where(album::id, eq(123)).sync();
|
||||||
|
|
||||||
actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
actual = session.select(album::info).where(album::id, eq(123)).sync().findFirst().get()._1;
|
||||||
Assert.assertNull(actual);
|
Assert.assertNull(actual);
|
||||||
|
|
||||||
// DELETE (D)
|
// DELETE (D)
|
||||||
session.delete().where(album::id, eq(123)).sync();
|
session.delete().where(album::id, eq(123)).sync();
|
||||||
|
|
||||||
long cnt = session.select(album::info).where(album::id, eq(123)).sync().count();
|
long cnt = session.select(album::info).where(album::id, eq(123)).sync().count();
|
||||||
Assert.assertEquals(0, cnt);
|
Assert.assertEquals(0, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoMapping() throws TimeoutException {
|
public void testNoMapping() throws TimeoutException {
|
||||||
|
|
||||||
TupleType tupleType = session.getMetadata().newTupleType(DataType.text(), DataType.text());
|
TupleType tupleType = session.getMetadata().newTupleType(DataType.text(), DataType.text());
|
||||||
TupleValue info = tupleType.newValue();
|
TupleValue info = tupleType.newValue();
|
||||||
|
|
||||||
info.setString(0, "Cassandra");
|
info.setString(0, "Cassandra");
|
||||||
info.setString(1, "San Jose");
|
info.setString(1, "San Jose");
|
||||||
|
|
||||||
// CREATE (C)
|
// CREATE (C)
|
||||||
|
|
||||||
session.insert().value(album::id, 555).value(album::infoNoMapping, info).sync();
|
session.insert().value(album::id, 555).value(album::infoNoMapping, info).sync();
|
||||||
|
|
||||||
// READ (R)
|
// READ (R)
|
||||||
|
|
||||||
TupleValue actual =
|
TupleValue actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
||||||
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(info.getString(0), actual.getString(0));
|
Assert.assertEquals(info.getString(0), actual.getString(0));
|
||||||
Assert.assertEquals(info.getString(1), actual.getString(1));
|
Assert.assertEquals(info.getString(1), actual.getString(1));
|
||||||
|
|
||||||
// UPDATE (U)
|
// UPDATE (U)
|
||||||
|
|
||||||
TupleValue expected = tupleType.newValue();
|
TupleValue expected = tupleType.newValue();
|
||||||
|
|
||||||
expected.setString(0, "Helenus");
|
expected.setString(0, "Helenus");
|
||||||
expected.setString(1, "Los Altos");
|
expected.setString(1, "Los Altos");
|
||||||
|
|
||||||
session.update().set(album::infoNoMapping, expected).where(album::id, eq(555)).sync();
|
session.update().set(album::infoNoMapping, expected).where(album::id, eq(555)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
||||||
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(expected.getString(0), actual.getString(0));
|
Assert.assertEquals(expected.getString(0), actual.getString(0));
|
||||||
Assert.assertEquals(expected.getString(1), actual.getString(1));
|
Assert.assertEquals(expected.getString(1), actual.getString(1));
|
||||||
|
|
||||||
// INSERT (I)
|
// INSERT (I)
|
||||||
// let's insert null ;)
|
// let's insert null ;)
|
||||||
|
|
||||||
session.update().set(album::infoNoMapping, null).where(album::id, eq(555)).sync();
|
session.update().set(album::infoNoMapping, null).where(album::id, eq(555)).sync();
|
||||||
|
|
||||||
actual =
|
actual = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
||||||
session.select(album::infoNoMapping).where(album::id, eq(555)).sync().findFirst().get()._1;
|
Assert.assertNull(actual);
|
||||||
Assert.assertNull(actual);
|
|
||||||
|
|
||||||
// DELETE (D)
|
// DELETE (D)
|
||||||
session.delete().where(album::id, eq(555)).sync();
|
session.delete().where(album::id, eq(555)).sync();
|
||||||
|
|
||||||
long cnt = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().count();
|
long cnt = session.select(album::infoNoMapping).where(album::id, eq(555)).sync().count();
|
||||||
Assert.assertEquals(0, cnt);
|
Assert.assertEquals(0, cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ import net.helenus.mapping.annotation.Tuple;
|
||||||
@Tuple
|
@Tuple
|
||||||
public interface Author {
|
public interface Author {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
String city();
|
String city();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,22 +18,23 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Book {
|
public interface Book {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
List<Author> authors();
|
List<Author> authors();
|
||||||
|
|
||||||
Set<Author> reviewers();
|
Set<Author> reviewers();
|
||||||
|
|
||||||
Map<Integer, Section> contents();
|
Map<Integer, Section> contents();
|
||||||
|
|
||||||
Map<Section, String> notes();
|
Map<Section, String> notes();
|
||||||
|
|
||||||
Map<Section, Author> writers();
|
Map<Section, Author> writers();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ import net.helenus.mapping.annotation.Tuple;
|
||||||
@Tuple
|
@Tuple
|
||||||
public interface Section {
|
public interface Section {
|
||||||
|
|
||||||
@Column(ordinal = 0)
|
@Column(ordinal = 0)
|
||||||
String title();
|
String title();
|
||||||
|
|
||||||
@Column(ordinal = 1)
|
@Column(ordinal = 1)
|
||||||
int page();
|
int page();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,124 +15,138 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.tuplecollection;
|
package net.helenus.test.integration.core.tuplecollection;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest {
|
public abstract class TupleCollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Book book;
|
static Book book;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
||||||
book = Helenus.dsl(Book.class, session.getMetadata());
|
book = Helenus.dsl(Book.class, session.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
System.out.println(book);
|
System.out.println(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class AuthorImpl implements Author {
|
public static final class AuthorImpl implements Author {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
String city;
|
String city;
|
||||||
|
|
||||||
AuthorImpl(String name, String city) {
|
AuthorImpl(String name, String city) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.city = city;
|
this.city = city;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String city() {
|
public String city() {
|
||||||
return city;
|
return city;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((city == null) ? 0 : city.hashCode());
|
result = prime * result + ((city == null) ? 0 : city.hashCode());
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj)
|
||||||
if (obj == null) return false;
|
return true;
|
||||||
if (getClass() != obj.getClass()) return false;
|
if (obj == null)
|
||||||
AuthorImpl other = (AuthorImpl) obj;
|
return false;
|
||||||
if (city == null) {
|
if (getClass() != obj.getClass())
|
||||||
if (other.city != null) return false;
|
return false;
|
||||||
} else if (!city.equals(other.city)) return false;
|
AuthorImpl other = (AuthorImpl) obj;
|
||||||
if (name == null) {
|
if (city == null) {
|
||||||
if (other.name != null) return false;
|
if (other.city != null)
|
||||||
} else if (!name.equals(other.name)) return false;
|
return false;
|
||||||
return true;
|
} else if (!city.equals(other.city))
|
||||||
}
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AuthorImpl [name=" + name + ", city=" + city + "]";
|
return "AuthorImpl [name=" + name + ", city=" + city + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class SectionImpl implements Section {
|
public static final class SectionImpl implements Section {
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
int page;
|
int page;
|
||||||
|
|
||||||
SectionImpl(String title, int page) {
|
SectionImpl(String title, int page) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String title() {
|
public String title() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int page() {
|
public int page() {
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + page;
|
result = prime * result + page;
|
||||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj)
|
||||||
if (obj == null) return false;
|
return true;
|
||||||
if (getClass() != obj.getClass()) return false;
|
if (obj == null)
|
||||||
SectionImpl other = (SectionImpl) obj;
|
return false;
|
||||||
if (page != other.page) return false;
|
if (getClass() != obj.getClass())
|
||||||
if (title == null) {
|
return false;
|
||||||
if (other.title != null) return false;
|
SectionImpl other = (SectionImpl) obj;
|
||||||
} else if (!title.equals(other.title)) return false;
|
if (page != other.page)
|
||||||
return true;
|
return false;
|
||||||
}
|
if (title == null) {
|
||||||
|
if (other.title != null)
|
||||||
|
return false;
|
||||||
|
} else if (!title.equals(other.title))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SectionImpl [title=" + title + ", page=" + page + "]";
|
return "SectionImpl [title=" + title + ", page=" + page + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,130 +18,123 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class TupleKeyMapTest extends TupleCollectionTest {
|
public class TupleKeyMapTest extends TupleCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyMapCRUID() throws TimeoutException {
|
public void testKeyMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 888;
|
int id = 888;
|
||||||
|
|
||||||
Map<Section, String> notes = new HashMap<Section, String>();
|
Map<Section, String> notes = new HashMap<Section, String>();
|
||||||
notes.put(new SectionImpl("first", 1), "value1");
|
notes.put(new SectionImpl("first", 1), "value1");
|
||||||
notes.put(new SectionImpl("second", 2), "value2");
|
notes.put(new SectionImpl("second", 2), "value2");
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::notes, notes).sync();
|
session.insert().value(book::id, id).value(book::notes, notes).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(notes, actual.notes());
|
assertEqualMaps(notes, actual.notes());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.writers());
|
Assert.assertNull(actual.writers());
|
||||||
Assert.assertNull(actual.contents());
|
Assert.assertNull(actual.contents());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Section, String> actualMap =
|
Map<Section, String> actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualMaps(notes, actualMap);
|
assertEqualMaps(notes, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql =
|
String cql = session.select(Query.get(book::notes, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
|
||||||
session
|
.cql();
|
||||||
.select(Query.get(book::notes, new SectionImpl("first", 1)))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.cql();
|
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Section, String> expected = new HashMap<Section, String>();
|
Map<Section, String> expected = new HashMap<Section, String>();
|
||||||
expected.put(new SectionImpl("f", 1), "v1");
|
expected.put(new SectionImpl("f", 1), "v1");
|
||||||
expected.put(new SectionImpl("s", 1), "v2");
|
expected.put(new SectionImpl("s", 1), "v2");
|
||||||
|
|
||||||
session.update().set(book::notes, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::notes, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.notes());
|
assertEqualMaps(expected, actual.notes());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
|
|
||||||
expected.put(third, "v3");
|
expected.put(third, "v3");
|
||||||
session.update().put(book::notes, third, "v3").where(book::id, Query.eq(id)).sync();
|
session.update().put(book::notes, third, "v3").where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(notes);
|
expected.putAll(notes);
|
||||||
session.update().putAll(book::notes, notes).where(book::id, Query.eq(id)).sync();
|
session.update().putAll(book::notes, notes).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
expected.put(third, "v33");
|
expected.put(third, "v33");
|
||||||
session.update().put(book::notes, third, "v33").where(book::id, Query.eq(id)).sync();
|
session.update().put(book::notes, third, "v33").where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(third);
|
expected.remove(third);
|
||||||
session.update().put(book::notes, third, null).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::notes, third, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::notes, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::notes, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::notes).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualMap);
|
||||||
Assert.assertNull(actualMap);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Section, String> expected, Map<Section, String> actual) {
|
private void assertEqualMaps(Map<Section, String> expected, Map<Section, String> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Section e : expected.keySet()) {
|
for (Section e : expected.keySet()) {
|
||||||
Section a =
|
Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
||||||
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
Assert.assertEquals(expected.get(e), actual.get(a));
|
||||||
Assert.assertEquals(expected.get(e), actual.get(a));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,157 +18,145 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class TupleListTest extends TupleCollectionTest {
|
public class TupleListTest extends TupleCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListCRUID() throws TimeoutException {
|
public void testListCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 777;
|
int id = 777;
|
||||||
|
|
||||||
List<Author> authors = new ArrayList<Author>();
|
List<Author> authors = new ArrayList<Author>();
|
||||||
authors.add(new AuthorImpl("Alex", "San Jose"));
|
authors.add(new AuthorImpl("Alex", "San Jose"));
|
||||||
authors.add(new AuthorImpl("Bob", "San Francisco"));
|
authors.add(new AuthorImpl("Bob", "San Francisco"));
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::authors, authors).sync();
|
session.insert().value(book::id, id).value(book::authors, authors).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualLists(authors, actual.authors());
|
assertEqualLists(authors, actual.authors());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.contents());
|
Assert.assertNull(actual.contents());
|
||||||
|
|
||||||
// read full list
|
// read full list
|
||||||
|
|
||||||
List<Author> actualList =
|
List<Author> actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualLists(authors, actualList);
|
assertEqualLists(authors, actualList);
|
||||||
|
|
||||||
// read single value by index
|
// read single value by index
|
||||||
|
|
||||||
String cql = session.select(Query.getIdx(book::authors, 1)).where(book::id, Query.eq(id)).cql();
|
String cql = session.select(Query.getIdx(book::authors, 1)).where(book::id, Query.eq(id)).cql();
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
List<Author> expected = new ArrayList<Author>();
|
List<Author> expected = new ArrayList<Author>();
|
||||||
expected.add(new AuthorImpl("Unknown", "City 17"));
|
expected.add(new AuthorImpl("Unknown", "City 17"));
|
||||||
|
|
||||||
session.update().set(book::authors, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::authors, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualLists(expected, actual.authors());
|
assertEqualLists(expected, actual.authors());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// prepend operation
|
// prepend operation
|
||||||
|
|
||||||
expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
|
expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
|
||||||
session
|
session.update().prepend(book::authors, new AuthorImpl("Prepend", "PrependCity")).where(book::id, Query.eq(id))
|
||||||
.update()
|
.sync();
|
||||||
.prepend(book::authors, new AuthorImpl("Prepend", "PrependCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// append operation
|
// append operation
|
||||||
|
|
||||||
expected.add(new AuthorImpl("Append", "AppendCity"));
|
expected.add(new AuthorImpl("Append", "AppendCity"));
|
||||||
session
|
session.update().append(book::authors, new AuthorImpl("Append", "AppendCity")).where(book::id, Query.eq(id))
|
||||||
.update()
|
.sync();
|
||||||
.append(book::authors, new AuthorImpl("Append", "AppendCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// prependAll operation
|
// prependAll operation
|
||||||
expected.addAll(0, authors);
|
expected.addAll(0, authors);
|
||||||
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// appendAll operation
|
// appendAll operation
|
||||||
expected.addAll(authors);
|
expected.addAll(authors);
|
||||||
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// set by Index
|
// set by Index
|
||||||
|
|
||||||
Author inserted = new AuthorImpl("Insert", "InsertCity");
|
Author inserted = new AuthorImpl("Insert", "InsertCity");
|
||||||
expected.set(5, inserted);
|
expected.set(5, inserted);
|
||||||
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
|
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
expected.remove(inserted);
|
expected.remove(inserted);
|
||||||
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
|
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.removeAll(authors);
|
expected.removeAll(authors);
|
||||||
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualList);
|
||||||
Assert.assertNull(actualList);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualLists(List<Author> expected, List<Author> actual) {
|
private void assertEqualLists(List<Author> expected, List<Author> actual) {
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
int size = expected.size();
|
int size = expected.size();
|
||||||
|
|
||||||
for (int i = 0; i != size; ++i) {
|
for (int i = 0; i != size; ++i) {
|
||||||
Author e = expected.get(i);
|
Author e = expected.get(i);
|
||||||
Author a = actual.get(i);
|
Author a = actual.get(i);
|
||||||
Assert.assertEquals(e.name(), a.name());
|
Assert.assertEquals(e.name(), a.name());
|
||||||
Assert.assertEquals(e.city(), a.city());
|
Assert.assertEquals(e.city(), a.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,140 +18,130 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class TupleMapTest extends TupleCollectionTest {
|
public class TupleMapTest extends TupleCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMapCRUID() throws TimeoutException {
|
public void testMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 333;
|
int id = 333;
|
||||||
|
|
||||||
Map<Section, Author> writers = new HashMap<Section, Author>();
|
Map<Section, Author> writers = new HashMap<Section, Author>();
|
||||||
writers.put(
|
writers.put(new SectionImpl("first", 1), new TupleCollectionTest.AuthorImpl("Alex", "San Jose"));
|
||||||
new SectionImpl("first", 1), new TupleCollectionTest.AuthorImpl("Alex", "San Jose"));
|
writers.put(new SectionImpl("second", 2), new TupleCollectionTest.AuthorImpl("Bob", "San Francisco"));
|
||||||
writers.put(
|
|
||||||
new SectionImpl("second", 2), new TupleCollectionTest.AuthorImpl("Bob", "San Francisco"));
|
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::writers, writers).sync();
|
session.insert().value(book::id, id).value(book::writers, writers).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual =
|
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
||||||
session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(id, actual.id());
|
assertEqualMaps(writers, actual.writers());
|
||||||
assertEqualMaps(writers, actual.writers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.notes());
|
||||||
Assert.assertNull(actual.notes());
|
Assert.assertNull(actual.contents());
|
||||||
Assert.assertNull(actual.contents());
|
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Section, Author> actualMap =
|
Map<Section, Author> actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualMaps(writers, actualMap);
|
assertEqualMaps(writers, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql =
|
String cql = session.select(Query.get(book::writers, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
|
||||||
session
|
.cql();
|
||||||
.select(Query.get(book::writers, new SectionImpl("first", 1)))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.cql();
|
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Section, Author> expected = new HashMap<Section, Author>();
|
Map<Section, Author> expected = new HashMap<Section, Author>();
|
||||||
expected.put(new SectionImpl("f", 1), new TupleCollectionTest.AuthorImpl("A", "SJ"));
|
expected.put(new SectionImpl("f", 1), new TupleCollectionTest.AuthorImpl("A", "SJ"));
|
||||||
expected.put(new SectionImpl("s", 1), new TupleCollectionTest.AuthorImpl("B", "SF"));
|
expected.put(new SectionImpl("s", 1), new TupleCollectionTest.AuthorImpl("B", "SF"));
|
||||||
|
|
||||||
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.writers());
|
assertEqualMaps(expected, actual.writers());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
Author unk = new TupleCollectionTest.AuthorImpl("Unk", "City 17");
|
Author unk = new TupleCollectionTest.AuthorImpl("Unk", "City 17");
|
||||||
|
|
||||||
expected.put(third, unk);
|
expected.put(third, unk);
|
||||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(writers);
|
expected.putAll(writers);
|
||||||
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
|
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
expected.put(third, unk);
|
expected.put(third, unk);
|
||||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(third);
|
expected.remove(third);
|
||||||
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualMap);
|
||||||
Assert.assertNull(actualMap);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Section, Author> expected, Map<Section, Author> actual) {
|
private void assertEqualMaps(Map<Section, Author> expected, Map<Section, Author> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Section e : expected.keySet()) {
|
for (Section e : expected.keySet()) {
|
||||||
Section a =
|
Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
||||||
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
|
||||||
|
|
||||||
Author ea = expected.get(e);
|
Author ea = expected.get(e);
|
||||||
Author aa = actual.get(a);
|
Author aa = actual.get(a);
|
||||||
|
|
||||||
Assert.assertEquals(ea.name(), aa.name());
|
Assert.assertEquals(ea.name(), aa.name());
|
||||||
Assert.assertEquals(ea.city(), aa.city());
|
Assert.assertEquals(ea.city(), aa.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,107 +18,100 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class TupleSetTest extends TupleCollectionTest {
|
public class TupleSetTest extends TupleCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetCRUID() throws TimeoutException {
|
public void testSetCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 555;
|
int id = 555;
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
Set<Author> reviewers = new HashSet<Author>();
|
Set<Author> reviewers = new HashSet<Author>();
|
||||||
reviewers.add(new AuthorImpl("Alex", "San Jose"));
|
reviewers.add(new AuthorImpl("Alex", "San Jose"));
|
||||||
reviewers.add(new AuthorImpl("Bob", "San Francisco"));
|
reviewers.add(new AuthorImpl("Bob", "San Francisco"));
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::reviewers, reviewers).sync();
|
session.insert().value(book::id, id).value(book::reviewers, reviewers).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualSets(reviewers, actual.reviewers());
|
assertEqualSets(reviewers, actual.reviewers());
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Set<Author> expected = new HashSet<Author>();
|
Set<Author> expected = new HashSet<Author>();
|
||||||
expected.add(new AuthorImpl("Craig", "Los Altos"));
|
expected.add(new AuthorImpl("Craig", "Los Altos"));
|
||||||
|
|
||||||
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
Set<Author> actualSet =
|
Set<Author> actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualSets(expected, actualSet);
|
assertEqualSets(expected, actualSet);
|
||||||
|
|
||||||
// add operation
|
// add operation
|
||||||
|
|
||||||
expected.add(new AuthorImpl("Add", "AddCity"));
|
expected.add(new AuthorImpl("Add", "AddCity"));
|
||||||
session
|
session.update().add(book::reviewers, new AuthorImpl("Add", "AddCity")).where(book::id, Query.eq(id)).sync();
|
||||||
.update()
|
|
||||||
.add(book::reviewers, new AuthorImpl("Add", "AddCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// addAll operation
|
// addAll operation
|
||||||
expected.addAll(reviewers);
|
expected.addAll(reviewers);
|
||||||
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
Author a = expected.stream().filter(p -> p.name().equals("Add")).findFirst().get();
|
Author a = expected.stream().filter(p -> p.name().equals("Add")).findFirst().get();
|
||||||
expected.remove(a);
|
expected.remove(a);
|
||||||
|
|
||||||
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
|
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.remove(expected.stream().filter(p -> p.name().equals("Alex")).findFirst().get());
|
expected.remove(expected.stream().filter(p -> p.name().equals("Alex")).findFirst().get());
|
||||||
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
|
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
|
||||||
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualSet);
|
||||||
Assert.assertNull(actualSet);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualSets(Set<Author> expected, Set<Author> actual) {
|
private void assertEqualSets(Set<Author> expected, Set<Author> actual) {
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Author e : expected) {
|
for (Author e : expected) {
|
||||||
Author a = actual.stream().filter(p -> p.name().equals(e.name())).findFirst().get();
|
Author a = actual.stream().filter(p -> p.name().equals(e.name())).findFirst().get();
|
||||||
Assert.assertEquals(e.city(), a.city());
|
Assert.assertEquals(e.city(), a.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,126 +18,123 @@ package net.helenus.test.integration.core.tuplecollection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class TupleValueMapTest extends TupleCollectionTest {
|
public class TupleValueMapTest extends TupleCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValueMapCRUID() throws TimeoutException {
|
public void testValueMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 999;
|
int id = 999;
|
||||||
|
|
||||||
Map<Integer, Section> contents = new HashMap<Integer, Section>();
|
Map<Integer, Section> contents = new HashMap<Integer, Section>();
|
||||||
contents.put(1, new SectionImpl("first", 1));
|
contents.put(1, new SectionImpl("first", 1));
|
||||||
contents.put(2, new SectionImpl("second", 2));
|
contents.put(2, new SectionImpl("second", 2));
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::contents, contents).sync();
|
session.insert().value(book::id, id).value(book::contents, contents).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(contents, actual.contents());
|
assertEqualMaps(contents, actual.contents());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.writers());
|
Assert.assertNull(actual.writers());
|
||||||
Assert.assertNull(actual.notes());
|
Assert.assertNull(actual.notes());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Integer, Section> actualMap =
|
Map<Integer, Section> actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync()
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.findFirst().get()._1;
|
||||||
assertEqualMaps(contents, actualMap);
|
assertEqualMaps(contents, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql = session.select(Query.get(book::contents, 1)).where(book::id, Query.eq(id)).cql();
|
String cql = session.select(Query.get(book::contents, 1)).where(book::id, Query.eq(id)).cql();
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Integer, Section> expected = new HashMap<Integer, Section>();
|
Map<Integer, Section> expected = new HashMap<Integer, Section>();
|
||||||
expected.put(4, new SectionImpl("4", 4));
|
expected.put(4, new SectionImpl("4", 4));
|
||||||
expected.put(5, new SectionImpl("5", 5));
|
expected.put(5, new SectionImpl("5", 5));
|
||||||
|
|
||||||
session.update().set(book::contents, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::contents, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.contents());
|
assertEqualMaps(expected, actual.contents());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
|
|
||||||
expected.put(3, third);
|
expected.put(3, third);
|
||||||
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(contents);
|
expected.putAll(contents);
|
||||||
session.update().putAll(book::contents, contents).where(book::id, Query.eq(id)).sync();
|
session.update().putAll(book::contents, contents).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
third = new SectionImpl("t-replace", 3);
|
third = new SectionImpl("t-replace", 3);
|
||||||
expected.put(3, third);
|
expected.put(3, third);
|
||||||
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::contents, 3, third).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(3);
|
expected.remove(3);
|
||||||
session.update().put(book::contents, 3, null).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::contents, 3, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::contents, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::contents, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::contents).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualMap);
|
||||||
Assert.assertNull(actualMap);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Integer, Section> expected, Map<Integer, Section> actual) {
|
private void assertEqualMaps(Map<Integer, Section> expected, Map<Integer, Section> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Integer i : expected.keySet()) {
|
for (Integer i : expected.keySet()) {
|
||||||
Section e = expected.get(i);
|
Section e = expected.get(i);
|
||||||
Section a = actual.get(i);
|
Section a = actual.get(i);
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT
|
@UDT
|
||||||
public interface Author {
|
public interface Author {
|
||||||
|
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
String city();
|
String city();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,22 +18,23 @@ package net.helenus.test.integration.core.udtcollection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Book {
|
public interface Book {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
int id();
|
int id();
|
||||||
|
|
||||||
List<Author> authors();
|
List<Author> authors();
|
||||||
|
|
||||||
Set<Author> reviewers();
|
Set<Author> reviewers();
|
||||||
|
|
||||||
Map<Integer, Section> contents();
|
Map<Integer, Section> contents();
|
||||||
|
|
||||||
Map<Section, String> notes();
|
Map<Section, String> notes();
|
||||||
|
|
||||||
Map<Section, Author> writers();
|
Map<Section, Author> writers();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT
|
@UDT
|
||||||
public interface Section {
|
public interface Section {
|
||||||
|
|
||||||
String title();
|
String title();
|
||||||
|
|
||||||
int page();
|
int page();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,125 +15,139 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.udtcollection;
|
package net.helenus.test.integration.core.udtcollection;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest {
|
public abstract class UDTCollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Book book;
|
static Book book;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
Helenus.clearDslCache();
|
Helenus.clearDslCache();
|
||||||
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Book.class).autoCreateDrop().get();
|
||||||
book = Helenus.dsl(Book.class);
|
book = Helenus.dsl(Book.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
System.out.println(book);
|
System.out.println(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class AuthorImpl implements Author {
|
public static final class AuthorImpl implements Author {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
String city;
|
String city;
|
||||||
|
|
||||||
AuthorImpl(String name, String city) {
|
AuthorImpl(String name, String city) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.city = city;
|
this.city = city;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String city() {
|
public String city() {
|
||||||
return city;
|
return city;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((city == null) ? 0 : city.hashCode());
|
result = prime * result + ((city == null) ? 0 : city.hashCode());
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj)
|
||||||
if (obj == null) return false;
|
return true;
|
||||||
if (getClass() != obj.getClass()) return false;
|
if (obj == null)
|
||||||
AuthorImpl other = (AuthorImpl) obj;
|
return false;
|
||||||
if (city == null) {
|
if (getClass() != obj.getClass())
|
||||||
if (other.city != null) return false;
|
return false;
|
||||||
} else if (!city.equals(other.city)) return false;
|
AuthorImpl other = (AuthorImpl) obj;
|
||||||
if (name == null) {
|
if (city == null) {
|
||||||
if (other.name != null) return false;
|
if (other.city != null)
|
||||||
} else if (!name.equals(other.name)) return false;
|
return false;
|
||||||
return true;
|
} else if (!city.equals(other.city))
|
||||||
}
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AuthorImpl [name=" + name + ", city=" + city + "]";
|
return "AuthorImpl [name=" + name + ", city=" + city + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class SectionImpl implements Section {
|
public static final class SectionImpl implements Section {
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
int page;
|
int page;
|
||||||
|
|
||||||
SectionImpl(String title, int page) {
|
SectionImpl(String title, int page) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String title() {
|
public String title() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int page() {
|
public int page() {
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + page;
|
result = prime * result + page;
|
||||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj)
|
||||||
if (obj == null) return false;
|
return true;
|
||||||
if (getClass() != obj.getClass()) return false;
|
if (obj == null)
|
||||||
SectionImpl other = (SectionImpl) obj;
|
return false;
|
||||||
if (page != other.page) return false;
|
if (getClass() != obj.getClass())
|
||||||
if (title == null) {
|
return false;
|
||||||
if (other.title != null) return false;
|
SectionImpl other = (SectionImpl) obj;
|
||||||
} else if (!title.equals(other.title)) return false;
|
if (page != other.page)
|
||||||
return true;
|
return false;
|
||||||
}
|
if (title == null) {
|
||||||
|
if (other.title != null)
|
||||||
|
return false;
|
||||||
|
} else if (!title.equals(other.title))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SectionImpl [title=" + title + ", page=" + page + "]";
|
return "SectionImpl [title=" + title + ", page=" + page + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,121 +21,120 @@ import static net.helenus.core.Query.get;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class UDTKeyMapTest extends UDTCollectionTest {
|
public class UDTKeyMapTest extends UDTCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyMapCRUID() throws TimeoutException {
|
public void testKeyMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 888;
|
int id = 888;
|
||||||
|
|
||||||
Map<Section, String> notes = new HashMap<Section, String>();
|
Map<Section, String> notes = new HashMap<Section, String>();
|
||||||
notes.put(new SectionImpl("first", 1), "value1");
|
notes.put(new SectionImpl("first", 1), "value1");
|
||||||
notes.put(new SectionImpl("second", 2), "value2");
|
notes.put(new SectionImpl("second", 2), "value2");
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::notes, notes).sync();
|
session.insert().value(book::id, id).value(book::notes, notes).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.<Book>select(book).where(book::id, eq(id)).sync().findFirst().get();
|
Book actual = session.<Book>select(book).where(book::id, eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(notes, actual.notes());
|
assertEqualMaps(notes, actual.notes());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.writers());
|
Assert.assertNull(actual.writers());
|
||||||
Assert.assertNull(actual.contents());
|
Assert.assertNull(actual.contents());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Section, String> actualMap =
|
Map<Section, String> actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst()
|
||||||
session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualMaps(notes, actualMap);
|
assertEqualMaps(notes, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql =
|
String cql = session.select(get(book::notes, new SectionImpl("first", 1))).where(book::id, eq(id)).cql();
|
||||||
session.select(get(book::notes, new SectionImpl("first", 1))).where(book::id, eq(id)).cql();
|
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Section, String> expected = new HashMap<Section, String>();
|
Map<Section, String> expected = new HashMap<Section, String>();
|
||||||
expected.put(new SectionImpl("f", 1), "v1");
|
expected.put(new SectionImpl("f", 1), "v1");
|
||||||
expected.put(new SectionImpl("s", 1), "v2");
|
expected.put(new SectionImpl("s", 1), "v2");
|
||||||
|
|
||||||
session.update().set(book::notes, expected).where(book::id, eq(id)).sync();
|
session.update().set(book::notes, expected).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book).where(book::id, eq(id)).sync().findFirst().get();
|
actual = session.<Book>select(book).where(book::id, eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.notes());
|
assertEqualMaps(expected, actual.notes());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
|
|
||||||
expected.put(third, "v3");
|
expected.put(third, "v3");
|
||||||
session.update().put(book::notes, third, "v3").where(book::id, eq(id)).sync();
|
session.update().put(book::notes, third, "v3").where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(notes);
|
expected.putAll(notes);
|
||||||
session.update().putAll(book::notes, notes).where(book::id, eq(id)).sync();
|
session.update().putAll(book::notes, notes).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
expected.put(third, "v33");
|
expected.put(third, "v33");
|
||||||
session.update().put(book::notes, third, "v33").where(book::id, eq(id)).sync();
|
session.update().put(book::notes, third, "v33").where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(third);
|
expected.remove(third);
|
||||||
session.update().put(book::notes, third, null).where(book::id, eq(id)).sync();
|
session.update().put(book::notes, third, null).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::notes, null).where(book::id, eq(id)).sync();
|
session.update().set(book::notes, null).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::notes).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
Assert.assertNull(actualMap);
|
Assert.assertNull(actualMap);
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, eq(id)).sync();
|
session.delete().where(book::id, eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, eq(id)).sync();
|
Long cnt = session.count().where(book::id, eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Section, String> expected, Map<Section, String> actual) {
|
private void assertEqualMaps(Map<Section, String> expected, Map<Section, String> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Section e : expected.keySet()) {
|
for (Section e : expected.keySet()) {
|
||||||
Section a =
|
Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
||||||
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
Assert.assertEquals(expected.get(e), actual.get(a));
|
||||||
Assert.assertEquals(expected.get(e), actual.get(a));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,157 +18,145 @@ package net.helenus.test.integration.core.udtcollection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class UDTListTest extends UDTCollectionTest {
|
public class UDTListTest extends UDTCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListCRUID() throws TimeoutException {
|
public void testListCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 777;
|
int id = 777;
|
||||||
|
|
||||||
List<Author> authors = new ArrayList<Author>();
|
List<Author> authors = new ArrayList<Author>();
|
||||||
authors.add(new AuthorImpl("Alex", "San Jose"));
|
authors.add(new AuthorImpl("Alex", "San Jose"));
|
||||||
authors.add(new AuthorImpl("Bob", "San Francisco"));
|
authors.add(new AuthorImpl("Bob", "San Francisco"));
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::authors, authors).sync();
|
session.insert().value(book::id, id).value(book::authors, authors).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualLists(authors, actual.authors());
|
assertEqualLists(authors, actual.authors());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.contents());
|
Assert.assertNull(actual.contents());
|
||||||
|
|
||||||
// read full list
|
// read full list
|
||||||
|
|
||||||
List<Author> actualList =
|
List<Author> actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualLists(authors, actualList);
|
assertEqualLists(authors, actualList);
|
||||||
|
|
||||||
// read single value by index
|
// read single value by index
|
||||||
|
|
||||||
String cql = session.select(Query.getIdx(book::authors, 1)).where(book::id, Query.eq(id)).cql();
|
String cql = session.select(Query.getIdx(book::authors, 1)).where(book::id, Query.eq(id)).cql();
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
List<Author> expected = new ArrayList<Author>();
|
List<Author> expected = new ArrayList<Author>();
|
||||||
expected.add(new AuthorImpl("Unknown", "City 17"));
|
expected.add(new AuthorImpl("Unknown", "City 17"));
|
||||||
|
|
||||||
session.update().set(book::authors, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::authors, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualLists(expected, actual.authors());
|
assertEqualLists(expected, actual.authors());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// prepend operation
|
// prepend operation
|
||||||
|
|
||||||
expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
|
expected.add(0, new AuthorImpl("Prepend", "PrependCity"));
|
||||||
session
|
session.update().prepend(book::authors, new AuthorImpl("Prepend", "PrependCity")).where(book::id, Query.eq(id))
|
||||||
.update()
|
.sync();
|
||||||
.prepend(book::authors, new AuthorImpl("Prepend", "PrependCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// append operation
|
// append operation
|
||||||
|
|
||||||
expected.add(new AuthorImpl("Append", "AppendCity"));
|
expected.add(new AuthorImpl("Append", "AppendCity"));
|
||||||
session
|
session.update().append(book::authors, new AuthorImpl("Append", "AppendCity")).where(book::id, Query.eq(id))
|
||||||
.update()
|
.sync();
|
||||||
.append(book::authors, new AuthorImpl("Append", "AppendCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// prependAll operation
|
// prependAll operation
|
||||||
expected.addAll(0, authors);
|
expected.addAll(0, authors);
|
||||||
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().prependAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// appendAll operation
|
// appendAll operation
|
||||||
expected.addAll(authors);
|
expected.addAll(authors);
|
||||||
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().appendAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// set by Index
|
// set by Index
|
||||||
|
|
||||||
Author inserted = new AuthorImpl("Insert", "InsertCity");
|
Author inserted = new AuthorImpl("Insert", "InsertCity");
|
||||||
expected.set(5, inserted);
|
expected.set(5, inserted);
|
||||||
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
|
session.update().setIdx(book::authors, 5, inserted).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
expected.remove(inserted);
|
expected.remove(inserted);
|
||||||
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
|
session.update().discard(book::authors, inserted).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.removeAll(authors);
|
expected.removeAll(authors);
|
||||||
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
session.update().discardAll(book::authors, authors).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualLists(expected, actualList);
|
||||||
assertEqualLists(expected, actualList);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::authors, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualList =
|
actualList = session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::authors).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualList);
|
||||||
Assert.assertNull(actualList);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualLists(List<Author> expected, List<Author> actual) {
|
private void assertEqualLists(List<Author> expected, List<Author> actual) {
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
int size = expected.size();
|
int size = expected.size();
|
||||||
|
|
||||||
for (int i = 0; i != size; ++i) {
|
for (int i = 0; i != size; ++i) {
|
||||||
Author e = expected.get(i);
|
Author e = expected.get(i);
|
||||||
Author a = actual.get(i);
|
Author a = actual.get(i);
|
||||||
Assert.assertEquals(e.name(), a.name());
|
Assert.assertEquals(e.name(), a.name());
|
||||||
Assert.assertEquals(e.city(), a.city());
|
Assert.assertEquals(e.city(), a.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,136 +18,129 @@ package net.helenus.test.integration.core.udtcollection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class UDTMapTest extends UDTCollectionTest {
|
public class UDTMapTest extends UDTCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMapCRUID() throws TimeoutException {
|
public void testMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 333;
|
int id = 333;
|
||||||
|
|
||||||
Map<Section, Author> writers = new HashMap<Section, Author>();
|
Map<Section, Author> writers = new HashMap<Section, Author>();
|
||||||
writers.put(new SectionImpl("first", 1), new AuthorImpl("Alex", "San Jose"));
|
writers.put(new SectionImpl("first", 1), new AuthorImpl("Alex", "San Jose"));
|
||||||
writers.put(new SectionImpl("second", 2), new AuthorImpl("Bob", "San Francisco"));
|
writers.put(new SectionImpl("second", 2), new AuthorImpl("Bob", "San Francisco"));
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::writers, writers).sync();
|
session.insert().value(book::id, id).value(book::writers, writers).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(writers, actual.writers());
|
assertEqualMaps(writers, actual.writers());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.notes());
|
Assert.assertNull(actual.notes());
|
||||||
Assert.assertNull(actual.contents());
|
Assert.assertNull(actual.contents());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Section, Author> actualMap =
|
Map<Section, Author> actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualMaps(writers, actualMap);
|
assertEqualMaps(writers, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql =
|
String cql = session.select(Query.get(book::writers, new SectionImpl("first", 1))).where(book::id, Query.eq(id))
|
||||||
session
|
.cql();
|
||||||
.select(Query.get(book::writers, new SectionImpl("first", 1)))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.cql();
|
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Section, Author> expected = new HashMap<Section, Author>();
|
Map<Section, Author> expected = new HashMap<Section, Author>();
|
||||||
expected.put(new SectionImpl("f", 1), new AuthorImpl("A", "SJ"));
|
expected.put(new SectionImpl("f", 1), new AuthorImpl("A", "SJ"));
|
||||||
expected.put(new SectionImpl("s", 1), new AuthorImpl("B", "SF"));
|
expected.put(new SectionImpl("s", 1), new AuthorImpl("B", "SF"));
|
||||||
|
|
||||||
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
actual = session.<Book>select(book).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.writers());
|
assertEqualMaps(expected, actual.writers());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
Author unk = new AuthorImpl("Unk", "City 17");
|
Author unk = new AuthorImpl("Unk", "City 17");
|
||||||
|
|
||||||
expected.put(third, unk);
|
expected.put(third, unk);
|
||||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(writers);
|
expected.putAll(writers);
|
||||||
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
|
session.update().putAll(book::writers, writers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
expected.put(third, unk);
|
expected.put(third, unk);
|
||||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(third);
|
expected.remove(third);
|
||||||
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualMaps(expected, actualMap);
|
||||||
assertEqualMaps(expected, actualMap);
|
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::writers, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap =
|
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualMap);
|
||||||
Assert.assertNull(actualMap);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Section, Author> expected, Map<Section, Author> actual) {
|
private void assertEqualMaps(Map<Section, Author> expected, Map<Section, Author> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Section e : expected.keySet()) {
|
for (Section e : expected.keySet()) {
|
||||||
Section a =
|
Section a = actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
||||||
actual.keySet().stream().filter(p -> p.title().equals(e.title())).findFirst().get();
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
|
||||||
|
|
||||||
Author ea = expected.get(e);
|
Author ea = expected.get(e);
|
||||||
Author aa = actual.get(a);
|
Author aa = actual.get(a);
|
||||||
|
|
||||||
Assert.assertEquals(ea.name(), aa.name());
|
Assert.assertEquals(ea.name(), aa.name());
|
||||||
Assert.assertEquals(ea.city(), aa.city());
|
Assert.assertEquals(ea.city(), aa.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,107 +18,100 @@ package net.helenus.test.integration.core.udtcollection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Query;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
|
||||||
public class UDTSetTest extends UDTCollectionTest {
|
public class UDTSetTest extends UDTCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetCRUID() throws TimeoutException {
|
public void testSetCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 555;
|
int id = 555;
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
Set<Author> reviewers = new HashSet<Author>();
|
Set<Author> reviewers = new HashSet<Author>();
|
||||||
reviewers.add(new AuthorImpl("Alex", "San Jose"));
|
reviewers.add(new AuthorImpl("Alex", "San Jose"));
|
||||||
reviewers.add(new AuthorImpl("Bob", "San Francisco"));
|
reviewers.add(new AuthorImpl("Bob", "San Francisco"));
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::reviewers, reviewers).sync();
|
session.insert().value(book::id, id).value(book::reviewers, reviewers).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
Book actual = session.select(Book.class).where(book::id, Query.eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualSets(reviewers, actual.reviewers());
|
assertEqualSets(reviewers, actual.reviewers());
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Set<Author> expected = new HashSet<Author>();
|
Set<Author> expected = new HashSet<Author>();
|
||||||
expected.add(new AuthorImpl("Craig", "Los Altos"));
|
expected.add(new AuthorImpl("Craig", "Los Altos"));
|
||||||
|
|
||||||
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::reviewers, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
Set<Author> actualSet =
|
Set<Author> actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst()
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualSets(expected, actualSet);
|
assertEqualSets(expected, actualSet);
|
||||||
|
|
||||||
// add operation
|
// add operation
|
||||||
|
|
||||||
expected.add(new AuthorImpl("Add", "AddCity"));
|
expected.add(new AuthorImpl("Add", "AddCity"));
|
||||||
session
|
session.update().add(book::reviewers, new AuthorImpl("Add", "AddCity")).where(book::id, Query.eq(id)).sync();
|
||||||
.update()
|
|
||||||
.add(book::reviewers, new AuthorImpl("Add", "AddCity"))
|
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// addAll operation
|
// addAll operation
|
||||||
expected.addAll(reviewers);
|
expected.addAll(reviewers);
|
||||||
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
session.update().addAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single value
|
// remove single value
|
||||||
|
|
||||||
Author a = expected.stream().filter(p -> p.name().equals("Add")).findFirst().get();
|
Author a = expected.stream().filter(p -> p.name().equals("Add")).findFirst().get();
|
||||||
expected.remove(a);
|
expected.remove(a);
|
||||||
|
|
||||||
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
|
session.update().remove(book::reviewers, a).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// remove values
|
// remove values
|
||||||
|
|
||||||
expected.remove(expected.stream().filter(p -> p.name().equals("Alex")).findFirst().get());
|
expected.remove(expected.stream().filter(p -> p.name().equals("Alex")).findFirst().get());
|
||||||
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
|
expected.remove(expected.stream().filter(p -> p.name().equals("Bob")).findFirst().get());
|
||||||
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
session.update().removeAll(book::reviewers, reviewers).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
assertEqualSets(expected, actualSet);
|
||||||
assertEqualSets(expected, actualSet);
|
|
||||||
|
|
||||||
// remove full list
|
// remove full list
|
||||||
|
|
||||||
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::reviewers, null).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualSet =
|
actualSet = session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
session.select(book::reviewers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
Assert.assertNull(actualSet);
|
||||||
Assert.assertNull(actualSet);
|
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, Query.eq(id)).sync();
|
session.delete().where(book::id, Query.eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(book::id, Query.eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualSets(Set<Author> expected, Set<Author> actual) {
|
private void assertEqualSets(Set<Author> expected, Set<Author> actual) {
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Author e : expected) {
|
for (Author e : expected) {
|
||||||
Author a = actual.stream().filter(p -> p.name().equals(e.name())).findFirst().get();
|
Author a = actual.stream().filter(p -> p.name().equals(e.name())).findFirst().get();
|
||||||
Assert.assertEquals(e.city(), a.city());
|
Assert.assertEquals(e.city(), a.city());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,120 +21,121 @@ import static net.helenus.core.Query.get;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class UDTValueMapTest extends UDTCollectionTest {
|
public class UDTValueMapTest extends UDTCollectionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValueMapCRUID() throws TimeoutException {
|
public void testValueMapCRUID() throws TimeoutException {
|
||||||
|
|
||||||
int id = 999;
|
int id = 999;
|
||||||
|
|
||||||
Map<Integer, Section> contents = new HashMap<Integer, Section>();
|
Map<Integer, Section> contents = new HashMap<Integer, Section>();
|
||||||
contents.put(1, new SectionImpl("first", 1));
|
contents.put(1, new SectionImpl("first", 1));
|
||||||
contents.put(2, new SectionImpl("second", 2));
|
contents.put(2, new SectionImpl("second", 2));
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
|
|
||||||
session.insert().value(book::id, id).value(book::contents, contents).sync();
|
session.insert().value(book::id, id).value(book::contents, contents).sync();
|
||||||
|
|
||||||
// READ
|
// READ
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.select(Book.class).where(book::id, eq(id)).sync().findFirst().get();
|
Book actual = session.select(Book.class).where(book::id, eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(contents, actual.contents());
|
assertEqualMaps(contents, actual.contents());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
Assert.assertNull(actual.writers());
|
Assert.assertNull(actual.writers());
|
||||||
Assert.assertNull(actual.notes());
|
Assert.assertNull(actual.notes());
|
||||||
|
|
||||||
// read full map
|
// read full map
|
||||||
|
|
||||||
Map<Integer, Section> actualMap =
|
Map<Integer, Section> actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst()
|
||||||
session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
.get()._1;
|
||||||
assertEqualMaps(contents, actualMap);
|
assertEqualMaps(contents, actualMap);
|
||||||
|
|
||||||
// read single key-value in map
|
// read single key-value in map
|
||||||
|
|
||||||
String cql = session.select(get(book::contents, 1)).where(book::id, eq(id)).cql();
|
String cql = session.select(get(book::contents, 1)).where(book::id, eq(id)).cql();
|
||||||
|
|
||||||
System.out.println("Still not supporting cql = " + cql);
|
System.out.println("Still not supporting cql = " + cql);
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
||||||
Map<Integer, Section> expected = new HashMap<Integer, Section>();
|
Map<Integer, Section> expected = new HashMap<Integer, Section>();
|
||||||
expected.put(4, new SectionImpl("4", 4));
|
expected.put(4, new SectionImpl("4", 4));
|
||||||
expected.put(5, new SectionImpl("5", 5));
|
expected.put(5, new SectionImpl("5", 5));
|
||||||
|
|
||||||
session.update().set(book::contents, expected).where(book::id, eq(id)).sync();
|
session.update().set(book::contents, expected).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actual = session.select(Book.class).where(book::id, eq(id)).sync().findFirst().get();
|
actual = session.select(Book.class).where(book::id, eq(id)).sync().findFirst().get();
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.contents());
|
assertEqualMaps(expected, actual.contents());
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
// put operation
|
// put operation
|
||||||
|
|
||||||
Section third = new SectionImpl("t", 3);
|
Section third = new SectionImpl("t", 3);
|
||||||
|
|
||||||
expected.put(3, third);
|
expected.put(3, third);
|
||||||
session.update().put(book::contents, 3, third).where(book::id, eq(id)).sync();
|
session.update().put(book::contents, 3, third).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
expected.putAll(contents);
|
expected.putAll(contents);
|
||||||
session.update().putAll(book::contents, contents).where(book::id, eq(id)).sync();
|
session.update().putAll(book::contents, contents).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// put existing
|
// put existing
|
||||||
|
|
||||||
third = new SectionImpl("t-replace", 3);
|
third = new SectionImpl("t-replace", 3);
|
||||||
expected.put(3, third);
|
expected.put(3, third);
|
||||||
session.update().put(book::contents, 3, third).where(book::id, eq(id)).sync();
|
session.update().put(book::contents, 3, third).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
||||||
// remove single key
|
// remove single key
|
||||||
|
|
||||||
expected.remove(3);
|
expected.remove(3);
|
||||||
session.update().put(book::contents, 3, null).where(book::id, eq(id)).sync();
|
session.update().put(book::contents, 3, null).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
assertEqualMaps(expected, actualMap);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// remove full map
|
// remove full map
|
||||||
|
|
||||||
session.update().set(book::contents, null).where(book::id, eq(id)).sync();
|
session.update().set(book::contents, null).where(book::id, eq(id)).sync();
|
||||||
|
|
||||||
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
actualMap = session.select(book::contents).where(book::id, eq(id)).sync().findFirst().get()._1;
|
||||||
Assert.assertNull(actualMap);
|
Assert.assertNull(actualMap);
|
||||||
|
|
||||||
// remove object
|
// remove object
|
||||||
|
|
||||||
session.delete().where(book::id, eq(id)).sync();
|
session.delete().where(book::id, eq(id)).sync();
|
||||||
Long cnt = session.count().where(book::id, eq(id)).sync();
|
Long cnt = session.count().where(book::id, eq(id)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertEqualMaps(Map<Integer, Section> expected, Map<Integer, Section> actual) {
|
private void assertEqualMaps(Map<Integer, Section> expected, Map<Integer, Section> actual) {
|
||||||
|
|
||||||
Assert.assertEquals(expected.size(), actual.size());
|
Assert.assertEquals(expected.size(), actual.size());
|
||||||
|
|
||||||
for (Integer i : expected.keySet()) {
|
for (Integer i : expected.keySet()) {
|
||||||
Section e = expected.get(i);
|
Section e = expected.get(i);
|
||||||
Section a = actual.get(i);
|
Section a = actual.get(i);
|
||||||
Assert.assertEquals(e.title(), a.title());
|
Assert.assertEquals(e.title(), a.title());
|
||||||
Assert.assertEquals(e.page(), a.page());
|
Assert.assertEquals(e.page(), a.page());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,133 +18,112 @@ package net.helenus.test.integration.core.unitofwork;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.UnitOfWork;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.UnitOfWork;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().autoCreateDrop().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAndThenOrdering() throws Exception {
|
public void testAndThenOrdering() throws Exception {
|
||||||
List<String> q = new ArrayList<String>(5);
|
List<String> q = new ArrayList<String>(5);
|
||||||
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
||||||
|
|
||||||
uow5 = session.begin();
|
uow5 = session.begin();
|
||||||
uow3 = session.begin(uow5);
|
uow3 = session.begin(uow5);
|
||||||
uow1 = session.begin(uow3);
|
uow1 = session.begin(uow3);
|
||||||
uow1.commit()
|
uow1.commit().andThen(() -> {
|
||||||
.andThen(
|
q.add("1");
|
||||||
() -> {
|
});
|
||||||
q.add("1");
|
uow2 = session.begin(uow3);
|
||||||
});
|
uow2.commit().andThen(() -> {
|
||||||
uow2 = session.begin(uow3);
|
q.add("2");
|
||||||
uow2.commit()
|
});
|
||||||
.andThen(
|
uow3.commit().andThen(() -> {
|
||||||
() -> {
|
q.add("3");
|
||||||
q.add("2");
|
});
|
||||||
});
|
uow4 = session.begin(uow5);
|
||||||
uow3.commit()
|
uow4.commit().andThen(() -> {
|
||||||
.andThen(
|
q.add("4");
|
||||||
() -> {
|
});
|
||||||
q.add("3");
|
uow5.commit().andThen(() -> {
|
||||||
});
|
q.add("5");
|
||||||
uow4 = session.begin(uow5);
|
});
|
||||||
uow4.commit()
|
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
q.add("4");
|
|
||||||
});
|
|
||||||
uow5.commit()
|
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
q.add("5");
|
|
||||||
});
|
|
||||||
|
|
||||||
System.out.println(q);
|
System.out.println(q);
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(Arrays.equals(q.toArray(new String[5]), new String[]{"1", "2", "3", "4", "5"}));
|
||||||
Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"}));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExceptionWithinAndThen() throws Exception {
|
public void testExceptionWithinAndThen() throws Exception {
|
||||||
List<String> q = new ArrayList<String>(5);
|
List<String> q = new ArrayList<String>(5);
|
||||||
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
||||||
|
|
||||||
uow5 = session.begin();
|
uow5 = session.begin();
|
||||||
uow4 = session.begin(uow5);
|
uow4 = session.begin(uow5);
|
||||||
try {
|
try {
|
||||||
uow3 = session.begin(uow4);
|
uow3 = session.begin(uow4);
|
||||||
uow1 = session.begin(uow3);
|
uow1 = session.begin(uow3);
|
||||||
uow1.commit()
|
uow1.commit().andThen(() -> {
|
||||||
.andThen(
|
q.add("1");
|
||||||
() -> {
|
});
|
||||||
q.add("1");
|
uow2 = session.begin(uow3);
|
||||||
});
|
uow2.commit().andThen(() -> {
|
||||||
uow2 = session.begin(uow3);
|
q.add("2");
|
||||||
uow2.commit()
|
});
|
||||||
.andThen(
|
uow3.commit().andThen(() -> {
|
||||||
() -> {
|
q.add("3");
|
||||||
q.add("2");
|
});
|
||||||
});
|
uow4.commit().andThen(() -> {
|
||||||
uow3.commit()
|
q.add("4");
|
||||||
.andThen(
|
});
|
||||||
() -> {
|
throw new Exception();
|
||||||
q.add("3");
|
} catch (Exception e) {
|
||||||
});
|
uow4.abort();
|
||||||
uow4.commit()
|
}
|
||||||
.andThen(
|
uow5.commit().andThen(() -> {
|
||||||
() -> {
|
q.add("5");
|
||||||
q.add("4");
|
});
|
||||||
});
|
|
||||||
throw new Exception();
|
|
||||||
} catch (Exception e) {
|
|
||||||
uow4.abort();
|
|
||||||
}
|
|
||||||
uow5.commit()
|
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
q.add("5");
|
|
||||||
});
|
|
||||||
|
|
||||||
System.out.println(q);
|
System.out.println(q);
|
||||||
Assert.assertTrue(q.isEmpty() == true);
|
Assert.assertTrue(q.isEmpty() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClosableWillAbortWhenNotCommitted() throws Exception {
|
public void testClosableWillAbortWhenNotCommitted() throws Exception {
|
||||||
UnitOfWork unitOfWork;
|
UnitOfWork unitOfWork;
|
||||||
try (UnitOfWork uow = session.begin()) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
unitOfWork = uow;
|
unitOfWork = uow;
|
||||||
Assert.assertFalse(uow.hasAborted());
|
Assert.assertFalse(uow.hasAborted());
|
||||||
}
|
}
|
||||||
Assert.assertTrue(unitOfWork.hasAborted());
|
Assert.assertTrue(unitOfWork.hasAborted());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClosable() throws Exception {
|
public void testClosable() throws Exception {
|
||||||
UnitOfWork unitOfWork;
|
UnitOfWork unitOfWork;
|
||||||
try (UnitOfWork uow = session.begin()) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
unitOfWork = uow;
|
unitOfWork = uow;
|
||||||
Assert.assertFalse(uow.hasAborted());
|
Assert.assertFalse(uow.hasAborted());
|
||||||
uow.commit()
|
uow.commit().andThen(() -> {
|
||||||
.andThen(
|
Assert.assertFalse(uow.hasAborted());
|
||||||
() -> {
|
Assert.assertTrue(uow.hasCommitted());
|
||||||
Assert.assertFalse(uow.hasAborted());
|
});
|
||||||
Assert.assertTrue(uow.hasCommitted());
|
}
|
||||||
});
|
Assert.assertFalse(unitOfWork.hasAborted());
|
||||||
}
|
Assert.assertTrue(unitOfWork.hasCommitted());
|
||||||
Assert.assertFalse(unitOfWork.hasAborted());
|
}
|
||||||
Assert.assertTrue(unitOfWork.hasCommitted());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType.Name;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import net.helenus.mapping.annotation.*;
|
|
||||||
|
import com.datastax.driver.core.DataType.Name;
|
||||||
|
|
||||||
|
import net.helenus.mapping.annotation.Types;
|
||||||
|
import net.helenus.mapping.annotation.UDT;
|
||||||
|
|
||||||
@UDT
|
@UDT
|
||||||
public interface Directory extends FilesystemNode {
|
public interface Directory extends FilesystemNode {
|
||||||
|
|
||||||
@Types.Set(Name.TIMEUUID)
|
@Types.Set(Name.TIMEUUID)
|
||||||
Set<FilesystemNode> inodes();
|
Set<FilesystemNode> inodes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.Column;
|
||||||
|
import net.helenus.mapping.annotation.UDT;
|
||||||
|
|
||||||
@UDT
|
@UDT
|
||||||
public interface File extends FilesystemNode {
|
public interface File extends FilesystemNode {
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
byte[] data();
|
byte[] data();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,5 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT
|
@UDT
|
||||||
public interface FileAttributes {
|
public interface FileAttributes {
|
||||||
|
|
||||||
String owner();
|
String owner();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,21 @@
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.helenus.mapping.annotation.*;
|
|
||||||
|
import net.helenus.mapping.annotation.ClusteringColumn;
|
||||||
|
import net.helenus.mapping.annotation.Column;
|
||||||
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table("fs")
|
@Table("fs")
|
||||||
public interface FilesystemNode {
|
public interface FilesystemNode {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID inode();
|
UUID inode();
|
||||||
|
|
||||||
@ClusteringColumn
|
@ClusteringColumn
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
FileAttributes attr();
|
FileAttributes attr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,223 +17,242 @@ package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import com.datastax.driver.core.utils.UUIDs;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.utils.UUIDs;
|
||||||
|
|
||||||
import net.bytebuddy.utility.RandomString;
|
import net.bytebuddy.utility.RandomString;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
import net.helenus.core.annotation.Cacheable;
|
import net.helenus.core.annotation.Cacheable;
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Constraints;
|
||||||
import net.helenus.mapping.annotation.Index;
|
import net.helenus.mapping.annotation.Index;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
@Cacheable
|
@Cacheable
|
||||||
interface Widget {
|
interface Widget {
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID id();
|
UUID id();
|
||||||
|
|
||||||
@Column
|
@Index
|
||||||
@Index
|
@Constraints.Distinct()
|
||||||
String name();
|
String name();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Widget widget;
|
static Widget widget;
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession()).showCql().add(Widget.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Widget.class).autoCreateDrop().get();
|
||||||
widget = session.dsl(Widget.class);
|
widget = session.dsl(Widget.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectAfterSelect() throws Exception {
|
public void testSelectAfterSelect() throws Exception {
|
||||||
Widget w1, w2, w3;
|
Widget w1, w2, w3, w4;
|
||||||
UUID key = UUIDs.timeBased();
|
UUID key = UUIDs.timeBased();
|
||||||
|
|
||||||
// This should inserted Widget, but not cache it.
|
// This should inserted Widget, but not cache it.
|
||||||
session
|
w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
|
||||||
.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
try (UnitOfWork uow = session.begin()) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
|
||||||
uow.setPurpose("testSelectAfterSelect");
|
uow.setPurpose("testSelectAfterSelect");
|
||||||
|
|
||||||
// This should read from the database and return a Widget.
|
// This should read from the database and return a Widget.
|
||||||
w1 =
|
w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||||
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
|
||||||
|
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
// This should read from the cache and get the same instance of a Widget.
|
||||||
w2 =
|
w3 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||||
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
|
||||||
|
|
||||||
uow.commit()
|
uow.commit().andThen(() -> {
|
||||||
.andThen(
|
Assert.assertEquals(w2, w3);
|
||||||
() -> {
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
w4 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync().orElse(null);
|
||||||
|
Assert.assertEquals(w4, w1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectAfterNestedSelect() throws Exception {
|
||||||
|
Widget w1, w2, w3, w4;
|
||||||
|
UUID key1 = UUIDs.timeBased();
|
||||||
|
UUID key2 = UUIDs.timeBased();
|
||||||
|
|
||||||
|
// This should inserted Widget, and not cache it in uow1.
|
||||||
|
try (UnitOfWork uow1 = session.begin()) {
|
||||||
|
w1 = session.<Widget>insert(widget).value(widget::id, key1).value(widget::name, RandomString.make(20))
|
||||||
|
.sync(uow1);
|
||||||
|
|
||||||
|
try (UnitOfWork uow2 = session.begin(uow1)) {
|
||||||
|
|
||||||
|
// This should read from uow1's cache and return the same Widget.
|
||||||
|
w2 = session.<Widget>select(widget).where(widget::id, eq(key1)).single().sync(uow2).orElse(null);
|
||||||
|
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
|
||||||
|
w3 = session.<Widget>insert(widget).value(widget::id, key2).value(widget::name, RandomString.make(20))
|
||||||
|
.sync(uow2);
|
||||||
|
|
||||||
|
uow2.commit().andThen(() -> {
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should read from the cache and get the same instance of a Widget.
|
||||||
|
w4 = session.<Widget>select(widget).where(widget::id, eq(key2)).single().sync(uow1).orElse(null);
|
||||||
|
|
||||||
|
uow1.commit().andThen(() -> {
|
||||||
|
Assert.assertEquals(w3, w4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectViaIndexAfterSelect() throws Exception {
|
||||||
|
Widget w1, w2;
|
||||||
|
UUID key = UUIDs.timeBased();
|
||||||
|
|
||||||
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
// This should insert and cache Widget in the uow.
|
||||||
|
session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync(uow);
|
||||||
|
|
||||||
|
// This should read from the database and return a Widget.
|
||||||
|
w1 = session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||||
|
|
||||||
|
// This should read from the cache and get the same instance of a Widget.
|
||||||
|
w2 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync(uow).orElse(null);
|
||||||
|
|
||||||
|
uow.commit().andThen(() -> {
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectAfterUpdated() throws Exception {
|
||||||
|
Widget w1, w2, w3, w4, w5, w6;
|
||||||
|
UUID key = UUIDs.timeBased();
|
||||||
|
|
||||||
|
// This should inserted Widget, but not cache it.
|
||||||
|
w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
|
||||||
|
|
||||||
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
|
||||||
|
// This should read from the database and return a Widget.
|
||||||
|
w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
|
||||||
|
.sync(uow).orElse(null);
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
|
||||||
|
// This should remove the object from the cache.
|
||||||
|
//TODO(gburd): w3 = session.
|
||||||
|
session.<Widget>update(w2)
|
||||||
|
.set(widget::name, "Bill")
|
||||||
|
.where(widget::id, eq(key))
|
||||||
|
.sync(uow);
|
||||||
|
|
||||||
|
// Fetch from session cache, should have old name.
|
||||||
|
w4 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
|
||||||
|
.sync().orElse(null);
|
||||||
|
Assert.assertEquals(w4, w2);
|
||||||
|
Assert.assertEquals(w4.name(), w1.name());
|
||||||
|
|
||||||
|
// This should skip the cache.
|
||||||
|
w5 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
|
||||||
|
.uncached()
|
||||||
|
.sync().orElse(null);
|
||||||
|
|
||||||
|
Assert.assertNotEquals(w5, w2); // Not the same instance
|
||||||
|
Assert.assertTrue(w2.equals(w5)); // But they have the same values
|
||||||
|
Assert.assertFalse(w5.equals(w2)); // TODO(gburd): should also work
|
||||||
|
Assert.assertEquals(w5.name(), "Bill");
|
||||||
|
|
||||||
|
uow.commit().andThen(() -> {
|
||||||
Assert.assertEquals(w1, w2);
|
Assert.assertEquals(w1, w2);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// The name changed, this should miss cache and not find anything in the database.
|
||||||
|
w6 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single()
|
||||||
|
.sync().orElse(null);
|
||||||
|
Assert.assertTrue(w2.equals(w5));
|
||||||
}
|
}
|
||||||
|
|
||||||
w3 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single().sync().orElse(null);
|
|
||||||
Assert.assertEquals(w1, w3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectAfterNestedSelect() throws Exception {
|
public void testSelectAfterDeleted() throws Exception {
|
||||||
Widget w1, w2, w3, w4;
|
Widget w1, w2, w3, w4;
|
||||||
UUID key1 = UUIDs.timeBased();
|
UUID key = UUIDs.timeBased();
|
||||||
UUID key2 = UUIDs.timeBased();
|
|
||||||
|
|
||||||
// This should inserted Widget, and not cache it in uow1.
|
// This should inserted Widget, but not cache it.
|
||||||
try (UnitOfWork uow1 = session.begin()) {
|
w1 = session.<Widget>insert(widget).value(widget::id, key).value(widget::name, RandomString.make(20)).sync();
|
||||||
w1 =
|
|
||||||
session
|
|
||||||
.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key1)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync(uow1);
|
|
||||||
|
|
||||||
try (UnitOfWork uow2 = session.begin(uow1)) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
|
||||||
// This should read from uow1's cache and return the same Widget.
|
// This should read from the database and return a Widget.
|
||||||
w2 =
|
w2 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
|
||||||
session
|
.sync(uow).orElse(null);
|
||||||
.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key1))
|
|
||||||
.single()
|
|
||||||
.sync(uow2)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(w1, w2);
|
// This should remove the object from the cache.
|
||||||
|
session.delete(widget).where(widget::id, eq(key))
|
||||||
|
.sync(uow);
|
||||||
|
|
||||||
w3 =
|
// This should fail to read from the cache.
|
||||||
session
|
w3 = session.<Widget>select(widget).where(widget::id, eq(key)).single()
|
||||||
.<Widget>insert(widget)
|
.sync(uow).orElse(null);
|
||||||
.value(widget::id, key2)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync(uow2);
|
|
||||||
|
|
||||||
uow2.commit()
|
Assert.assertEquals(w3, null);
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
Assert.assertEquals(w1, w2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
uow.commit().andThen(() -> {
|
||||||
w4 =
|
|
||||||
session
|
|
||||||
.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key2))
|
|
||||||
.single()
|
|
||||||
.sync(uow1)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
uow1.commit()
|
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
Assert.assertEquals(w3, w4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSelectViaIndexAfterSelect() throws Exception {
|
|
||||||
Widget w1, w2;
|
|
||||||
UUID key = UUIDs.timeBased();
|
|
||||||
|
|
||||||
try (UnitOfWork uow = session.begin()) {
|
|
||||||
// This should insert and cache Widget in the uow.
|
|
||||||
session
|
|
||||||
.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync(uow);
|
|
||||||
|
|
||||||
// This should read from the database and return a Widget.
|
|
||||||
w1 =
|
|
||||||
session
|
|
||||||
.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key))
|
|
||||||
.single()
|
|
||||||
.sync(uow)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
|
||||||
w2 =
|
|
||||||
session
|
|
||||||
.<Widget>select(widget)
|
|
||||||
.where(widget::name, eq(w1.name()))
|
|
||||||
.single()
|
|
||||||
.sync(uow)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
uow.commit()
|
|
||||||
.andThen(
|
|
||||||
() -> {
|
|
||||||
Assert.assertEquals(w1, w2);
|
Assert.assertEquals(w1, w2);
|
||||||
});
|
Assert.assertEquals(w3, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
w4 = session.<Widget>select(widget).where(widget::name, eq(w1.name())).single()
|
||||||
|
.sync().orElse(null);
|
||||||
|
|
||||||
|
Assert.assertEquals(w4, null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Test
|
* @Test public void testSelectAfterInsertProperlyCachesEntity() throws
|
||||||
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
|
* Exception { Widget w1, w2, w3, w4; UUID key = UUIDs.timeBased();
|
||||||
Widget w1, w2, w3, w4;
|
*
|
||||||
UUID key = UUIDs.timeBased();
|
* try (UnitOfWork uow = session.begin()) {
|
||||||
|
*
|
||||||
try (UnitOfWork uow = session.begin()) {
|
* // This should cache the inserted Widget. w1 = session.<Widget>insert(widget)
|
||||||
|
* .value(widget::id, key) .value(widget::name, RandomString.make(20))
|
||||||
// This should cache the inserted Widget.
|
* .sync(uow);
|
||||||
w1 = session.<Widget>insert(widget)
|
*
|
||||||
.value(widget::id, key)
|
* // This should read from the cache and get the same instance of a Widget. w2
|
||||||
.value(widget::name, RandomString.make(20))
|
* = session.<Widget>select(widget) .where(widget::id, eq(key)) .single()
|
||||||
.sync(uow);
|
* .sync(uow) .orElse(null);
|
||||||
|
*
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
* uow.commit() .andThen(() -> { Assert.assertEquals(w1, w2); }); }
|
||||||
w2 = session.<Widget>select(widget)
|
*
|
||||||
.where(widget::id, eq(key))
|
* // This should read the widget from the session cache and maintain object
|
||||||
.single()
|
* identity. w3 = session.<Widget>select(widget) .where(widget::id, eq(key))
|
||||||
.sync(uow)
|
* .single() .sync() .orElse(null);
|
||||||
.orElse(null);
|
*
|
||||||
|
* Assert.assertEquals(w1, w3);
|
||||||
uow.commit()
|
*
|
||||||
.andThen(() -> {
|
* // This should read the widget from the database, no object identity but
|
||||||
Assert.assertEquals(w1, w2);
|
* values should match. w4 = session.<Widget>select(widget) .where(widget::id,
|
||||||
});
|
* eq(key)) .uncached() .single() .sync() .orElse(null);
|
||||||
}
|
*
|
||||||
|
* Assert.assertNotEquals(w1, w4); Assert.assertTrue(w1.equals(w4)); }
|
||||||
// This should read the widget from the session cache and maintain object identity.
|
*/
|
||||||
w3 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key))
|
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(w1, w3);
|
|
||||||
|
|
||||||
// This should read the widget from the database, no object identity but values should match.
|
|
||||||
w4 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key))
|
|
||||||
.ignoreCache()
|
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertNotEquals(w1, w4);
|
|
||||||
Assert.assertTrue(w1.equals(w4));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package net.helenus.test.integration.core.usertype;
|
package net.helenus.test.integration.core.usertype;
|
||||||
|
|
||||||
import com.datastax.driver.core.UDTValue;
|
import com.datastax.driver.core.UDTValue;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
@ -24,13 +25,13 @@ import net.helenus.mapping.annotation.Types;
|
||||||
@Table
|
@Table
|
||||||
public interface Account {
|
public interface Account {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
long id();
|
long id();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
Address address();
|
Address address();
|
||||||
|
|
||||||
@Types.UDT("address")
|
@Types.UDT("address")
|
||||||
@Column
|
@Column
|
||||||
UDTValue addressNoMapping();
|
UDTValue addressNoMapping();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.usertype;
|
package net.helenus.test.integration.core.usertype;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.DataType;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.Types;
|
import net.helenus.mapping.annotation.Types;
|
||||||
import net.helenus.mapping.annotation.UDT;
|
import net.helenus.mapping.annotation.UDT;
|
||||||
|
@ -24,19 +26,19 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT("address")
|
@UDT("address")
|
||||||
public interface Address {
|
public interface Address {
|
||||||
|
|
||||||
@Column(ordinal = 0, value = "line_1")
|
@Column(ordinal = 0, value = "line_1")
|
||||||
String street();
|
String street();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
String city();
|
String city();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
int zip();
|
int zip();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
String country();
|
String country();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Types.Set(DataType.Name.TEXT)
|
@Types.Set(DataType.Name.TEXT)
|
||||||
Set<String> phones();
|
Set<String> phones();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT
|
@UDT
|
||||||
public interface AddressInformation {
|
public interface AddressInformation {
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
Address address();
|
Address address();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.helenus.test.integration.core.usertype;
|
package net.helenus.test.integration.core.usertype;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
@ -8,9 +9,9 @@ import net.helenus.mapping.annotation.Table;
|
||||||
@Table
|
@Table
|
||||||
public interface Customer {
|
public interface Customer {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID id();
|
UUID id();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
AddressInformation addressInformation();
|
AddressInformation addressInformation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,118 +15,111 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.usertype;
|
package net.helenus.test.integration.core.usertype;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.Query;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
|
public class InnerUserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Customer customer;
|
static Customer customer;
|
||||||
static AddressInformation addressInformation;
|
static AddressInformation addressInformation;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
Helenus.clearDslCache();
|
Helenus.clearDslCache();
|
||||||
session = Helenus.init(getSession()).showCql().add(Customer.class).autoCreateDrop().get();
|
session = Helenus.init(getSession()).showCql().add(Customer.class).autoCreateDrop().get();
|
||||||
customer = Helenus.dsl(Customer.class);
|
customer = Helenus.dsl(Customer.class);
|
||||||
addressInformation = Helenus.dsl(AddressInformation.class);
|
addressInformation = Helenus.dsl(AddressInformation.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterTest() {
|
public static void afterTest() {
|
||||||
session.getSession().execute("DROP TABLE IF EXISTS customer;");
|
session.getSession().execute("DROP TABLE IF EXISTS customer;");
|
||||||
session.getSession().execute("DROP TYPE IF EXISTS address_information;");
|
session.getSession().execute("DROP TYPE IF EXISTS address_information;");
|
||||||
// SchemaUtil.dropUserType(session.getSessionRepository().findUserType("address_information")), true);
|
// SchemaUtil.dropUserType(session.getSessionRepository().findUserType("address_information")),
|
||||||
}
|
// true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrint() {
|
public void testPrint() {
|
||||||
System.out.println(addressInformation);
|
System.out.println(addressInformation);
|
||||||
System.out.println(customer);
|
System.out.println(customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCrud() throws TimeoutException {
|
public void testCrud() throws TimeoutException {
|
||||||
|
|
||||||
UUID id = UUID.randomUUID();
|
UUID id = UUID.randomUUID();
|
||||||
|
|
||||||
Address a =
|
Address a = new Address() {
|
||||||
new Address() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String street() {
|
public String street() {
|
||||||
return "1 st";
|
return "1 st";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String city() {
|
public String city() {
|
||||||
return "San Jose";
|
return "San Jose";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int zip() {
|
public int zip() {
|
||||||
return 95131;
|
return 95131;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String country() {
|
public String country() {
|
||||||
return "USA";
|
return "USA";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> phones() {
|
public Set<String> phones() {
|
||||||
return Sets.newHashSet("14080000000");
|
return Sets.newHashSet("14080000000");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressInformation ai =
|
AddressInformation ai = new AddressInformation() {
|
||||||
new AddressInformation() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address address() {
|
public Address address() {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
session.insert().value(customer::id, id).value(customer::addressInformation, ai).sync();
|
session.insert().value(customer::id, id).value(customer::addressInformation, ai).sync();
|
||||||
|
|
||||||
String cql =
|
String cql = session.update().set(customer.addressInformation().address()::street, "3 st")
|
||||||
session
|
.where(customer::id, Query.eq(id)).cql();
|
||||||
.update()
|
|
||||||
.set(customer.addressInformation().address()::street, "3 st")
|
|
||||||
.where(customer::id, Query.eq(id))
|
|
||||||
.cql();
|
|
||||||
|
|
||||||
//TODO: System.out.println("At the time when this test was written Cassandra did not support queries like this: " + cql);
|
// TODO: System.out.println("At the time when this test was written Cassandra
|
||||||
|
// did not support queries like this: " + cql);
|
||||||
|
|
||||||
session.update().set(customer::addressInformation, ai).where(customer::id, Query.eq(id)).sync();
|
session.update().set(customer::addressInformation, ai).where(customer::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
String street =
|
String street = session.select(customer.addressInformation().address()::street)
|
||||||
session
|
.where(customer::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||||
.select(customer.addressInformation().address()::street)
|
|
||||||
.where(customer::id, Query.eq(id))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals("1 st", street);
|
Assert.assertEquals("1 st", street);
|
||||||
|
|
||||||
session.delete().where(customer::id, Query.eq(id)).sync();
|
session.delete().where(customer::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
Long cnt = session.count().where(customer::id, Query.eq(id)).sync();
|
Long cnt = session.count().where(customer::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,242 +15,204 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.usertype;
|
package net.helenus.test.integration.core.usertype;
|
||||||
|
|
||||||
import com.datastax.driver.core.UDTValue;
|
|
||||||
import com.datastax.driver.core.UserType;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.core.Query;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.UDTValue;
|
||||||
|
import com.datastax.driver.core.UserType;
|
||||||
|
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.core.Query;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
|
|
||||||
public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
|
public class UserDefinedTypeTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Address address;
|
static Address address;
|
||||||
static Account account;
|
static Account account;
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
public static class AccountImpl implements Account {
|
@BeforeClass
|
||||||
|
public static void beforeTest() {
|
||||||
|
session = Helenus.init(getSession()).showCql().add(Account.class).autoCreateDrop().get();
|
||||||
|
address = Helenus.dsl(Address.class);
|
||||||
|
account = Helenus.dsl(Account.class);
|
||||||
|
}
|
||||||
|
|
||||||
long id;
|
@Test
|
||||||
Address address;
|
public void testPrint() {
|
||||||
UDTValue addressNoMapping;
|
System.out.println(address);
|
||||||
|
System.out.println(account);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Test
|
||||||
public long id() {
|
public void testMappingCRUID() throws TimeoutException {
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
AddressImpl addr = new AddressImpl();
|
||||||
public Address address() {
|
addr.street = "1 st";
|
||||||
return address;
|
addr.city = "San Jose";
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
AccountImpl acc = new AccountImpl();
|
||||||
public UDTValue addressNoMapping() {
|
acc.id = 123L;
|
||||||
return addressNoMapping;
|
acc.address = addr;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AddressImpl implements Address {
|
// CREATE
|
||||||
|
|
||||||
String street;
|
session.upsert(acc).sync();
|
||||||
String city;
|
|
||||||
int zip;
|
|
||||||
String country;
|
|
||||||
Set<String> phones;
|
|
||||||
|
|
||||||
@Override
|
// READ
|
||||||
public String street() {
|
|
||||||
return street;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
String streetName = session.select(account.address()::street).where(account::id, Query.eq(123L)).sync()
|
||||||
public String city() {
|
.findFirst().get()._1;
|
||||||
return city;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Assert.assertEquals("1 st", streetName);
|
||||||
public int zip() {
|
|
||||||
return zip;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// UPDATE
|
||||||
public String country() {
|
|
||||||
return country;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
AddressImpl expected = new AddressImpl();
|
||||||
public Set<String> phones() {
|
expected.street = "2 st";
|
||||||
return phones;
|
expected.city = "San Francisco";
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
session.update().set(account::address, expected).where(account::id, Query.eq(123L)).sync();
|
||||||
public static void beforeTest() {
|
|
||||||
session = Helenus.init(getSession()).showCql().add(Account.class).autoCreateDrop().get();
|
|
||||||
address = Helenus.dsl(Address.class);
|
|
||||||
account = Helenus.dsl(Account.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
Address actual = session.select(account::address).where(account::id, Query.eq(123L)).sync().findFirst()
|
||||||
public void testPrint() {
|
.get()._1;
|
||||||
System.out.println(address);
|
|
||||||
System.out.println(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
Assert.assertEquals(expected.street(), actual.street());
|
||||||
public void testMappingCRUID() throws TimeoutException {
|
Assert.assertEquals(expected.city(), actual.city());
|
||||||
|
Assert.assertNull(actual.country());
|
||||||
|
Assert.assertEquals(0, actual.zip());
|
||||||
|
|
||||||
AddressImpl addr = new AddressImpl();
|
// INSERT using UPDATE
|
||||||
addr.street = "1 st";
|
session.update().set(account::address, null).where(account::id, Query.eq(123L)).sync();
|
||||||
addr.city = "San Jose";
|
|
||||||
|
|
||||||
AccountImpl acc = new AccountImpl();
|
Address adrNull = session.select(account::address).where(account::id, Query.eq(123L)).sync().findFirst()
|
||||||
acc.id = 123L;
|
.get()._1;
|
||||||
acc.address = addr;
|
Assert.assertNull(adrNull);
|
||||||
|
|
||||||
// CREATE
|
// DELETE
|
||||||
|
|
||||||
session.upsert(acc).sync();
|
session.delete().where(account::id, Query.eq(123L)).sync();
|
||||||
|
|
||||||
// READ
|
Long cnt = session.count().where(account::id, Query.eq(123L)).sync();
|
||||||
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
|
}
|
||||||
|
|
||||||
String streetName =
|
@Test
|
||||||
session
|
public void testNoMapping() throws TimeoutException {
|
||||||
.select(account.address()::street)
|
|
||||||
.where(account::id, Query.eq(123L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals("1 st", streetName);
|
String ks = getSession().getLoggedKeyspace();
|
||||||
|
UserType addressType = getSession().getCluster().getMetadata().getKeyspace(ks).getUserType("address");
|
||||||
|
|
||||||
// UPDATE
|
UDTValue addressNoMapping = addressType.newValue();
|
||||||
|
addressNoMapping.setString("line_1", "1st street");
|
||||||
|
addressNoMapping.setString("city", "San Jose");
|
||||||
|
|
||||||
AddressImpl expected = new AddressImpl();
|
AccountImpl acc = new AccountImpl();
|
||||||
expected.street = "2 st";
|
acc.id = 777L;
|
||||||
expected.city = "San Francisco";
|
acc.addressNoMapping = addressNoMapping;
|
||||||
|
|
||||||
session.update().set(account::address, expected).where(account::id, Query.eq(123L)).sync();
|
// CREATE
|
||||||
|
|
||||||
Address actual =
|
session.upsert(acc).sync();
|
||||||
session
|
|
||||||
.select(account::address)
|
|
||||||
.where(account::id, Query.eq(123L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(expected.street(), actual.street());
|
// READ
|
||||||
Assert.assertEquals(expected.city(), actual.city());
|
|
||||||
Assert.assertNull(actual.country());
|
|
||||||
Assert.assertEquals(0, actual.zip());
|
|
||||||
|
|
||||||
// INSERT using UPDATE
|
UDTValue found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
|
||||||
session.update().set(account::address, null).where(account::id, Query.eq(123L)).sync();
|
.get()._1;
|
||||||
|
|
||||||
Address adrNull =
|
Assert.assertEquals(addressNoMapping.getType(), found.getType());
|
||||||
session
|
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
|
||||||
.select(account::address)
|
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
|
||||||
.where(account::id, Query.eq(123L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertNull(adrNull);
|
|
||||||
|
|
||||||
// DELETE
|
// UPDATE
|
||||||
|
|
||||||
session.delete().where(account::id, Query.eq(123L)).sync();
|
addressNoMapping = addressType.newValue();
|
||||||
|
addressNoMapping.setString("line_1", "Market street");
|
||||||
|
addressNoMapping.setString("city", "San Francisco");
|
||||||
|
|
||||||
Long cnt = session.count().where(account::id, Query.eq(123L)).sync();
|
session.update().set(account::addressNoMapping, addressNoMapping).where(account::id, Query.eq(777L)).sync();
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
|
||||||
public void testNoMapping() throws TimeoutException {
|
.get()._1;
|
||||||
|
|
||||||
String ks = getSession().getLoggedKeyspace();
|
Assert.assertEquals(addressNoMapping.getType(), found.getType());
|
||||||
UserType addressType =
|
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
|
||||||
getSession().getCluster().getMetadata().getKeyspace(ks).getUserType("address");
|
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
|
||||||
|
|
||||||
UDTValue addressNoMapping = addressType.newValue();
|
// INSERT using UPDATE
|
||||||
addressNoMapping.setString("line_1", "1st street");
|
session.update().set(account::addressNoMapping, null).where(account::id, Query.eq(777L)).sync();
|
||||||
addressNoMapping.setString("city", "San Jose");
|
|
||||||
|
|
||||||
AccountImpl acc = new AccountImpl();
|
found = session.select(account::addressNoMapping).where(account::id, Query.eq(777L)).sync().findFirst()
|
||||||
acc.id = 777L;
|
.get()._1;
|
||||||
acc.addressNoMapping = addressNoMapping;
|
Assert.assertNull(found);
|
||||||
|
|
||||||
// CREATE
|
// DELETE
|
||||||
|
|
||||||
session.upsert(acc).sync();
|
session.delete().where(account::id, Query.eq(777L)).sync();
|
||||||
|
|
||||||
// READ
|
Long cnt = session.count().where(account::id, Query.eq(777L)).sync();
|
||||||
|
Assert.assertEquals(Long.valueOf(0), cnt);
|
||||||
|
}
|
||||||
|
|
||||||
UDTValue found =
|
public static class AccountImpl implements Account {
|
||||||
session
|
|
||||||
.select(account::addressNoMapping)
|
|
||||||
.where(account::id, Query.eq(777L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(addressNoMapping.getType(), found.getType());
|
long id;
|
||||||
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
|
Address address;
|
||||||
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
|
UDTValue addressNoMapping;
|
||||||
|
|
||||||
// UPDATE
|
@Override
|
||||||
|
public long id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
addressNoMapping = addressType.newValue();
|
@Override
|
||||||
addressNoMapping.setString("line_1", "Market street");
|
public Address address() {
|
||||||
addressNoMapping.setString("city", "San Francisco");
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
session
|
@Override
|
||||||
.update()
|
public UDTValue addressNoMapping() {
|
||||||
.set(account::addressNoMapping, addressNoMapping)
|
return addressNoMapping;
|
||||||
.where(account::id, Query.eq(777L))
|
}
|
||||||
.sync();
|
}
|
||||||
|
|
||||||
found =
|
public static class AddressImpl implements Address {
|
||||||
session
|
|
||||||
.select(account::addressNoMapping)
|
|
||||||
.where(account::id, Query.eq(777L))
|
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
|
|
||||||
Assert.assertEquals(addressNoMapping.getType(), found.getType());
|
String street;
|
||||||
Assert.assertEquals(addressNoMapping.getString("line_1"), found.getString("line_1"));
|
String city;
|
||||||
Assert.assertEquals(addressNoMapping.getString("city"), found.getString("city"));
|
int zip;
|
||||||
|
String country;
|
||||||
|
Set<String> phones;
|
||||||
|
|
||||||
// INSERT using UPDATE
|
@Override
|
||||||
session.update().set(account::addressNoMapping, null).where(account::id, Query.eq(777L)).sync();
|
public String street() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
found =
|
@Override
|
||||||
session
|
public String city() {
|
||||||
.select(account::addressNoMapping)
|
return city;
|
||||||
.where(account::id, Query.eq(777L))
|
}
|
||||||
.sync()
|
|
||||||
.findFirst()
|
|
||||||
.get()
|
|
||||||
._1;
|
|
||||||
Assert.assertNull(found);
|
|
||||||
|
|
||||||
// DELETE
|
@Override
|
||||||
|
public int zip() {
|
||||||
|
return zip;
|
||||||
|
}
|
||||||
|
|
||||||
session.delete().where(account::id, Query.eq(777L)).sync();
|
@Override
|
||||||
|
public String country() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
Long cnt = session.count().where(account::id, Query.eq(777L)).sync();
|
@Override
|
||||||
Assert.assertEquals(Long.valueOf(0), cnt);
|
public Set<String> phones() {
|
||||||
}
|
return phones;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,25 @@ package net.helenus.test.integration.core.views;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.ClusteringColumn;
|
import net.helenus.mapping.annotation.ClusteringColumn;
|
||||||
import net.helenus.mapping.annotation.CoveringIndex;
|
import net.helenus.mapping.annotation.CoveringIndex;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
@CoveringIndex(
|
@CoveringIndex(name = "cyclist_mv", covering = {"age", "birthday", "country"}, partitionKeys = {"age",
|
||||||
name = "cyclist_mv",
|
"cid"}, clusteringColumns = {})
|
||||||
covering = {"age", "birthday", "country"},
|
|
||||||
partitionKeys = {"age", "cid"},
|
|
||||||
clusteringColumns = {}
|
|
||||||
)
|
|
||||||
public interface Cyclist {
|
public interface Cyclist {
|
||||||
@ClusteringColumn
|
@ClusteringColumn
|
||||||
UUID cid();
|
UUID cid();
|
||||||
|
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
int age();
|
int age();
|
||||||
|
|
||||||
Date birthday();
|
Date birthday();
|
||||||
|
|
||||||
String country();
|
String country();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,23 @@ package net.helenus.test.integration.core.views;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.helenus.mapping.OrderingDirection;
|
import net.helenus.mapping.OrderingDirection;
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.ClusteringColumn;
|
||||||
|
import net.helenus.mapping.annotation.Index;
|
||||||
|
import net.helenus.mapping.annotation.MaterializedView;
|
||||||
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
|
|
||||||
@MaterializedView
|
@MaterializedView
|
||||||
public interface CyclistsByAge extends Cyclist {
|
public interface CyclistsByAge extends Cyclist {
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID cid();
|
UUID cid();
|
||||||
|
|
||||||
@ClusteringColumn(ordering = OrderingDirection.ASC)
|
@ClusteringColumn(ordering = OrderingDirection.ASC)
|
||||||
int age();
|
int age();
|
||||||
|
|
||||||
Date birthday();
|
Date birthday();
|
||||||
|
|
||||||
@Index
|
@Index
|
||||||
String country();
|
String country();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,16 @@ import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
// See: https://docs.datastax.com/en/cql/3.3/cql/cql_using/useCreateMV.html
|
// See: https://docs.datastax.com/en/cql/3.3/cql/cql_using/useCreateMV.html
|
||||||
// https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateMaterializedView.html
|
// https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateMaterializedView.html
|
||||||
|
@ -33,45 +36,35 @@ import org.junit.Test;
|
||||||
// https://cassandra-zone.com/materialized-views/
|
// https://cassandra-zone.com/materialized-views/
|
||||||
public class MaterializedViewTest extends AbstractEmbeddedCassandraTest {
|
public class MaterializedViewTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Cyclist cyclist;
|
static Cyclist cyclist;
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
static Date dateFromString(String dateInString) {
|
static Date dateFromString(String dateInString) {
|
||||||
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
|
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
|
||||||
try {
|
try {
|
||||||
return formatter.parse(dateInString);
|
return formatter.parse(dateInString);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session =
|
session = Helenus.init(getSession()).showCql().add(Cyclist.class).add(CyclistsByAge.class).autoCreateDrop()
|
||||||
Helenus.init(getSession())
|
.get();
|
||||||
.showCql()
|
cyclist = session.dsl(Cyclist.class);
|
||||||
.add(Cyclist.class)
|
|
||||||
.add(CyclistsByAge.class)
|
|
||||||
.autoCreateDrop()
|
|
||||||
.get();
|
|
||||||
cyclist = session.dsl(Cyclist.class);
|
|
||||||
|
|
||||||
//try {
|
try {
|
||||||
session
|
session.insert(cyclist).value(cyclist::cid, UUID.randomUUID()).value(cyclist::age, 18)
|
||||||
.insert(cyclist)
|
.value(cyclist::birthday, dateFromString("1997-02-08")).value(cyclist::country, "Netherlands")
|
||||||
.value(cyclist::cid, UUID.randomUUID())
|
.value(cyclist::name, "Pascal EENKHOORN").sync();
|
||||||
.value(cyclist::age, 18)
|
} catch (TimeoutException e) {
|
||||||
.value(cyclist::birthday, dateFromString("1997-02-08"))
|
}
|
||||||
.value(cyclist::country, "Netherlands")
|
}
|
||||||
.value(cyclist::name, "Pascal EENKHOORN")
|
|
||||||
.sync();
|
|
||||||
//} catch (TimeoutException e) {
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMv() throws TimeoutException {
|
public void testMv() throws TimeoutException {
|
||||||
session.select(Cyclist.class).from(CyclistsByAge.class).where(cyclist::age, eq(18)).sync();
|
session.select(Cyclist.class).from(CyclistsByAge.class).where(cyclist::age, eq(18)).sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue