Merge branch 'develop' into 2.1.x-SNAPSHOT
This commit is contained in:
commit
265c35c4c6
71 changed files with 1624 additions and 1066 deletions
7
bin/format.sh
Executable file
7
bin/format.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
for f in $(find ./src -name \*.java); do
|
||||
echo Formatting $f
|
||||
java -jar ./lib/google-java-format-1.3-all-deps.jar --replace $f
|
||||
done
|
||||
|
BIN
lib/google-java-format-1.3-all-deps.jar
Normal file
BIN
lib/google-java-format-1.3-all-deps.jar
Normal file
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
package com.datastax.driver.core.querybuilder;
|
||||
|
||||
import com.datastax.driver.core.CodecRegistry;
|
||||
import java.util.List;
|
||||
|
||||
public class IsNotNullClause extends Clause {
|
||||
|
||||
final String name;
|
||||
|
||||
public IsNotNullClause(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
Object firstValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendTo(StringBuilder sb, List<Object> variables, CodecRegistry codecRegistry) {
|
||||
Utils.appendName(name, sb).append(" IS NOT NULL");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsBindMarker() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.datastax.driver.core.schemabuilder;
|
||||
|
||||
import com.datastax.driver.core.CodecRegistry;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
public class CreateMaterializedView extends Create {
|
||||
|
||||
private String viewName;
|
||||
private Select.Where selection;
|
||||
private String primaryKey;
|
||||
|
||||
public CreateMaterializedView(
|
||||
String keyspaceName, String viewName, Select.Where selection, String primaryKey) {
|
||||
super(keyspaceName, viewName);
|
||||
this.viewName = viewName;
|
||||
this.selection = selection;
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
public String getQueryString(CodecRegistry codecRegistry) {
|
||||
return buildInternal();
|
||||
}
|
||||
|
||||
public String buildInternal() {
|
||||
StringBuilder createStatement =
|
||||
new StringBuilder(STATEMENT_START).append("CREATE MATERIALIZED VIEW");
|
||||
if (ifNotExists) {
|
||||
createStatement.append(" IF NOT EXISTS");
|
||||
}
|
||||
createStatement.append(" ");
|
||||
if (keyspaceName.isPresent()) {
|
||||
createStatement.append(keyspaceName.get()).append(".");
|
||||
}
|
||||
createStatement.append(viewName);
|
||||
createStatement.append(" AS ");
|
||||
createStatement.append(selection.getQueryString());
|
||||
createStatement.setLength(createStatement.length() - 1);
|
||||
createStatement.append(" ");
|
||||
createStatement.append(primaryKey);
|
||||
createStatement.append(";");
|
||||
|
||||
return createStatement.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return buildInternal();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.datastax.driver.core.schemabuilder;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
public class DropMaterializedView extends Drop {
|
||||
|
||||
enum DroppedItem {
|
||||
TABLE,
|
||||
TYPE,
|
||||
INDEX,
|
||||
MATERIALIZED_VIEW
|
||||
}
|
||||
|
||||
private Optional<String> keyspaceName = Optional.absent();
|
||||
private String itemName;
|
||||
private boolean ifExists = true;
|
||||
private final String itemType = "MATERIALIZED VIEW";
|
||||
|
||||
public DropMaterializedView(String keyspaceName, String viewName) {
|
||||
this(keyspaceName, viewName, DroppedItem.MATERIALIZED_VIEW);
|
||||
}
|
||||
|
||||
private DropMaterializedView(String keyspaceName, String viewName, DroppedItem itemType) {
|
||||
super(keyspaceName, viewName, Drop.DroppedItem.TABLE);
|
||||
validateNotEmpty(keyspaceName, "Keyspace name");
|
||||
this.keyspaceName = Optional.fromNullable(keyspaceName);
|
||||
this.itemName = viewName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the 'IF EXISTS' condition to this DROP statement.
|
||||
*
|
||||
* @return this statement.
|
||||
*/
|
||||
public Drop ifExists() {
|
||||
this.ifExists = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildInternal() {
|
||||
StringBuilder dropStatement = new StringBuilder("DROP " + itemType + " ");
|
||||
if (ifExists) {
|
||||
dropStatement.append("IF EXISTS ");
|
||||
}
|
||||
if (keyspaceName.isPresent()) {
|
||||
dropStatement.append(keyspaceName.get()).append(".");
|
||||
}
|
||||
|
||||
dropStatement.append(itemName);
|
||||
return dropStatement.toString();
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
package net.helenus.core;
|
||||
|
||||
import net.helenus.core.reflect.MapExportable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
|
||||
import net.helenus.core.reflect.MapExportable;
|
||||
|
||||
public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<E> {
|
||||
|
||||
|
@ -37,5 +35,4 @@ public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<
|
|||
public Date createdAt() {
|
||||
return (Date) get("createdAt", Date.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
package net.helenus.core;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.primitives.Primitives;
|
||||
|
||||
import java.util.*;
|
||||
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
||||
import net.helenus.core.reflect.Drafted;
|
||||
import net.helenus.core.reflect.MapExportable;
|
||||
import net.helenus.mapping.MappingUtil;
|
||||
|
||||
|
||||
public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
||||
|
||||
private final Map<String, Object> backingMap = new HashMap<String, Object>();
|
||||
private final MapExportable entity;
|
||||
private final Map<String, Object> entityMap;
|
||||
|
||||
|
||||
public AbstractEntityDraft(MapExportable entity) {
|
||||
this.entity = entity;
|
||||
this.entityMap = entity != null ? entity.toMap() : new HashMap<String, Object>();
|
||||
|
@ -24,7 +20,9 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
|||
|
||||
public abstract Class<E> getEntityClass();
|
||||
|
||||
public E build() { return Helenus.map(getEntityClass(), toMap()); }
|
||||
public E build() {
|
||||
return Helenus.map(getEntityClass(), toMap());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T get(Getter<T> getter, Class<?> returnType) {
|
||||
|
@ -96,9 +94,7 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
|||
}
|
||||
|
||||
private <T> String methodNameFor(Getter<T> getter) {
|
||||
return MappingUtil.resolveMappingProperty(getter)
|
||||
.getProperty()
|
||||
.getPropertyName();
|
||||
return MappingUtil.resolveMappingProperty(getter).getProperty().getPropertyName();
|
||||
}
|
||||
|
||||
public <T> Object unset(Getter<T> getter) {
|
||||
|
@ -160,5 +156,4 @@ public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
|||
public String toString() {
|
||||
return backingMap.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import com.datastax.driver.core.querybuilder.BuiltStatement;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||
import net.helenus.mapping.value.ColumnValueProvider;
|
||||
import net.helenus.support.HelenusException;
|
||||
|
@ -124,5 +123,4 @@ public abstract class AbstractSessionOperations {
|
|||
void printCql(String cql) {
|
||||
getPrintStream().println(cql);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,10 +17,8 @@ package net.helenus.core;
|
|||
|
||||
import com.diffplug.common.base.Errors;
|
||||
import com.google.common.collect.TreeTraverser;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
||||
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork, AutoCloseable {
|
||||
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
|
||||
|
@ -70,7 +68,9 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Set<Object>> getCache() { return cache; }
|
||||
public Map<String, Set<Object>> getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
private Iterator<AbstractUnitOfWork<E>> getChildNodes() {
|
||||
return nested.iterator();
|
||||
|
@ -85,7 +85,8 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
public PostCommitFunction<Void, Void> commit() throws E {
|
||||
// All nested UnitOfWork should be committed (not aborted) before calls to commit, check.
|
||||
boolean canCommit = true;
|
||||
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
|
||||
TreeTraverser<AbstractUnitOfWork<E>> traverser =
|
||||
TreeTraverser.using(node -> node::getChildNodes);
|
||||
for (AbstractUnitOfWork<E> uow : traverser.postOrderTraversal(this)) {
|
||||
if (this != uow) {
|
||||
canCommit &= (!uow.aborted && uow.committed);
|
||||
|
@ -112,7 +113,8 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
if (parentCache.containsKey(key)) {
|
||||
// merge the sets
|
||||
Set<Object> ps = parentCache.get(key);
|
||||
ps.addAll(cache.get(key)); //TODO(gburd): review this, likely not correct in all cases as-is.
|
||||
ps.addAll(
|
||||
cache.get(key)); //TODO(gburd): review this, likely not correct in all cases as-is.
|
||||
} else {
|
||||
// add the missing set
|
||||
parentCache.put(key, cache.get(key));
|
||||
|
@ -122,7 +124,10 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
|
||||
// Apply all post-commit functions for
|
||||
if (parent == null) {
|
||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
||||
traverser
|
||||
.postOrderTraversal(this)
|
||||
.forEach(
|
||||
uow -> {
|
||||
uow.applyPostCommitFunctions();
|
||||
});
|
||||
return new PostCommitFunction(this, null);
|
||||
|
@ -137,8 +142,12 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
|
||||
/* Explicitly discard the work and mark it as as such in the log. */
|
||||
public void abort() {
|
||||
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
|
||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
||||
TreeTraverser<AbstractUnitOfWork<E>> traverser =
|
||||
TreeTraverser.using(node -> node::getChildNodes);
|
||||
traverser
|
||||
.postOrderTraversal(this)
|
||||
.forEach(
|
||||
uow -> {
|
||||
uow.committed = false;
|
||||
uow.aborted = true;
|
||||
});
|
||||
|
@ -165,5 +174,4 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
|||
public boolean hasCommitted() {
|
||||
return committed;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.helenus.core;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CommitThunk {
|
||||
|
|
|
@ -15,10 +15,21 @@
|
|||
*/
|
||||
package net.helenus.core;
|
||||
|
||||
import static net.helenus.core.Query.eq;
|
||||
|
||||
import brave.Tracer;
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.datastax.driver.core.*;
|
||||
import java.io.Closeable;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
import net.helenus.core.operation.*;
|
||||
import net.helenus.core.reflect.Drafted;
|
||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||
|
@ -33,19 +44,6 @@ import net.helenus.support.Fun.Tuple6;
|
|||
import net.helenus.support.HelenusException;
|
||||
import net.helenus.support.HelenusMappingException;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static net.helenus.core.Query.eq;
|
||||
|
||||
public final class HelenusSession extends AbstractSessionOperations implements Closeable {
|
||||
|
||||
private final int MAX_CACHE_SIZE = 10000;
|
||||
|
@ -69,7 +67,6 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
private final StatementColumnValuePreparer valuePreparer;
|
||||
private final Metadata metadata;
|
||||
|
||||
|
||||
HelenusSession(
|
||||
Session session,
|
||||
String usingKeyspace,
|
||||
|
@ -177,9 +174,13 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultQueryIdempotency() { return defaultQueryIdempotency; }
|
||||
public boolean getDefaultQueryIdempotency() {
|
||||
return defaultQueryIdempotency;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() { return metadata; }
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public synchronized UnitOfWork begin() {
|
||||
return begin(null);
|
||||
|
@ -188,20 +189,27 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
public synchronized UnitOfWork begin(UnitOfWork parent) {
|
||||
try {
|
||||
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);
|
||||
if (parent != null) {
|
||||
parent.addNestedUnitOfWork(uow);
|
||||
}
|
||||
return uow.begin();
|
||||
}
|
||||
catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||
throw new HelenusException(String.format("Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()), e);
|
||||
} catch (NoSuchMethodException
|
||||
| InvocationTargetException
|
||||
| InstantiationException
|
||||
| IllegalAccessException e) {
|
||||
throw new HelenusException(
|
||||
String.format(
|
||||
"Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
public <E> SelectOperation<E> select(E pojo) {
|
||||
Objects.requireNonNull(pojo, "supplied object must be a dsl for a registered entity but cannot be null");
|
||||
Objects.requireNonNull(
|
||||
pojo, "supplied object must be a dsl for a registered entity but cannot be null");
|
||||
ColumnValueProvider valueProvider = getValueProvider();
|
||||
HelenusEntity entity = Helenus.resolve(pojo);
|
||||
Class<?> entityClass = entity.getMappingInterface();
|
||||
|
@ -239,7 +247,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
}
|
||||
|
||||
public <E> SelectOperation<Row> selectAll(E pojo) {
|
||||
Objects.requireNonNull(pojo, "supplied object must be a dsl for a registered entity but cannot be null");
|
||||
Objects.requireNonNull(
|
||||
pojo, "supplied object must be a dsl for a registered entity but cannot be null");
|
||||
HelenusEntity entity = Helenus.resolve(pojo);
|
||||
return new SelectOperation<Row>(this, entity);
|
||||
}
|
||||
|
@ -411,7 +420,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
|
||||
public <E> UpdateOperation<E> update(Drafted<E> drafted) {
|
||||
if (drafted instanceof AbstractEntityDraft == false) {
|
||||
throw new HelenusMappingException("update of draft objects that don't inherit from AbstractEntityDraft is not yet supported");
|
||||
throw new HelenusMappingException(
|
||||
"update of draft objects that don't inherit from AbstractEntityDraft is not yet supported");
|
||||
}
|
||||
AbstractEntityDraft<E> draft = (AbstractEntityDraft<E>) drafted;
|
||||
UpdateOperation update = new UpdateOperation<E>(this, draft);
|
||||
|
@ -420,7 +430,10 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
HelenusEntity entity = Helenus.entity(draft.getEntityClass());
|
||||
|
||||
// Add all the mutated values contained in the draft.
|
||||
entity.getOrderedProperties().forEach(property -> {
|
||||
entity
|
||||
.getOrderedProperties()
|
||||
.forEach(
|
||||
property -> {
|
||||
switch (property.getColumnType()) {
|
||||
case PARTITION_KEY:
|
||||
case CLUSTERING_COLUMN:
|
||||
|
@ -429,10 +442,12 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
String propertyName = property.getPropertyName();
|
||||
if (mutatedProperties.contains(propertyName)) {
|
||||
Object value = map.get(propertyName);
|
||||
Getter<Object> getter = new Getter<Object>() {
|
||||
Getter<Object> getter =
|
||||
new Getter<Object>() {
|
||||
@Override
|
||||
public Object get() {
|
||||
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
|
||||
throw new DslPropertyException(
|
||||
new HelenusPropertyNode(property, Optional.empty()));
|
||||
}
|
||||
};
|
||||
update.set(getter, value);
|
||||
|
@ -441,16 +456,21 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
});
|
||||
|
||||
// Add the partition and clustering keys if they were in the draft (normally the case).
|
||||
entity.getOrderedProperties().forEach(property -> {
|
||||
entity
|
||||
.getOrderedProperties()
|
||||
.forEach(
|
||||
property -> {
|
||||
switch (property.getColumnType()) {
|
||||
case PARTITION_KEY:
|
||||
case CLUSTERING_COLUMN:
|
||||
String propertyName = property.getPropertyName();
|
||||
Object value = map.get(propertyName);
|
||||
Getter<Object> getter = new Getter<Object>() {
|
||||
Getter<Object> getter =
|
||||
new Getter<Object>() {
|
||||
@Override
|
||||
public Object get() {
|
||||
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
|
||||
throw new DslPropertyException(
|
||||
new HelenusPropertyNode(property, Optional.empty()));
|
||||
}
|
||||
};
|
||||
update.where(getter, eq(value));
|
||||
|
@ -478,9 +498,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
}
|
||||
|
||||
public <T> InsertOperation<T> insert(T pojo) {
|
||||
Objects.requireNonNull(pojo, "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
|
||||
Objects.requireNonNull(
|
||||
pojo,
|
||||
"supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
|
||||
HelenusEntity entity = null;
|
||||
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
|
||||
try {
|
||||
entity = Helenus.resolve(pojo);
|
||||
} catch (HelenusMappingException e) {
|
||||
}
|
||||
if (entity != null) {
|
||||
return new InsertOperation<T>(this, entity.getMappingInterface(), true);
|
||||
} else {
|
||||
|
@ -488,7 +513,9 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
}
|
||||
}
|
||||
|
||||
public <T> InsertOperation<T> insert(Drafted draft) { return insert(draft.build(), draft.mutated()); }
|
||||
public <T> InsertOperation<T> insert(Drafted draft) {
|
||||
return insert(draft.build(), draft.mutated());
|
||||
}
|
||||
|
||||
private <T> InsertOperation<T> insert(T pojo, Set<String> mutations) {
|
||||
Objects.requireNonNull(pojo, "pojo is empty");
|
||||
|
@ -512,9 +539,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
}
|
||||
|
||||
public <T> InsertOperation<T> upsert(T pojo) {
|
||||
Objects.requireNonNull(pojo, "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
|
||||
Objects.requireNonNull(
|
||||
pojo,
|
||||
"supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
|
||||
HelenusEntity entity = null;
|
||||
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
|
||||
try {
|
||||
entity = Helenus.resolve(pojo);
|
||||
} catch (HelenusMappingException e) {
|
||||
}
|
||||
if (entity != null) {
|
||||
return new InsertOperation<T>(this, entity.getMappingInterface(), false);
|
||||
} else {
|
||||
|
@ -587,5 +619,4 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package net.helenus.core;
|
||||
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PostCommitFunction<T, R> implements java.util.function.Function<T, R> {
|
||||
|
||||
|
|
|
@ -17,16 +17,21 @@ package net.helenus.core;
|
|||
|
||||
import com.datastax.driver.core.*;
|
||||
import com.datastax.driver.core.IndexMetadata;
|
||||
import com.datastax.driver.core.querybuilder.IsNotNullClause;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
import com.datastax.driver.core.schemabuilder.*;
|
||||
import com.datastax.driver.core.schemabuilder.Create.Options;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||
import net.helenus.mapping.*;
|
||||
import net.helenus.mapping.ColumnType;
|
||||
import net.helenus.mapping.type.OptionalColumnMetadata;
|
||||
import net.helenus.support.CqlUtil;
|
||||
import net.helenus.support.HelenusMappingException;
|
||||
|
||||
|
||||
public final class SchemaUtil {
|
||||
|
||||
private SchemaUtil() {}
|
||||
|
@ -143,6 +148,67 @@ public final class SchemaUtil {
|
|||
return SchemaBuilder.dropType(type.getTypeName()).ifExists();
|
||||
}
|
||||
|
||||
public static SchemaStatement createMaterializedView(
|
||||
String keyspace, String viewName, HelenusEntity entity) {
|
||||
if (entity.getType() != HelenusEntityType.VIEW) {
|
||||
throw new HelenusMappingException("expected view entity " + entity);
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new HelenusMappingException("no entity or table to select data");
|
||||
}
|
||||
|
||||
List<HelenusPropertyNode> props = new ArrayList<HelenusPropertyNode>();
|
||||
entity
|
||||
.getOrderedProperties()
|
||||
.stream()
|
||||
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
||||
.forEach(p -> props.add(p));
|
||||
|
||||
Select.Selection selection = QueryBuilder.select();
|
||||
|
||||
for (HelenusPropertyNode prop : props) {
|
||||
String columnName = prop.getColumnName();
|
||||
selection = selection.column(columnName);
|
||||
}
|
||||
String tableName =
|
||||
Helenus.entity(entity.getMappingInterface().getInterfaces()[0]).getName().toCql();
|
||||
Select.Where where = selection.from(tableName).where();
|
||||
List<String> p = new ArrayList<String>(props.size());
|
||||
List<String> c = new ArrayList<String>(props.size());
|
||||
|
||||
for (HelenusPropertyNode prop : props) {
|
||||
String columnName = prop.getColumnName();
|
||||
switch (prop.getProperty().getColumnType()) {
|
||||
case PARTITION_KEY:
|
||||
p.add(columnName);
|
||||
where = where.and(new IsNotNullClause(columnName));
|
||||
break;
|
||||
case CLUSTERING_COLUMN:
|
||||
c.add(columnName);
|
||||
where = where.and(new IsNotNullClause(columnName));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String primaryKey =
|
||||
"PRIMARY KEY ("
|
||||
+ ((p.size() > 1) ? "(" + String.join(", ", p) + ")" : p.get(0))
|
||||
+ ((c.size() > 0)
|
||||
? ", " + ((c.size() > 1) ? "(" + String.join(", ", c) + ")" : c.get(0))
|
||||
: "")
|
||||
+ ")";
|
||||
|
||||
return new CreateMaterializedView(keyspace, viewName, where, primaryKey);
|
||||
}
|
||||
|
||||
public static SchemaStatement dropMaterializedView(
|
||||
String keyspace, String viewName, HelenusEntity entity) {
|
||||
return new DropMaterializedView(keyspace, viewName);
|
||||
}
|
||||
|
||||
public static SchemaStatement createTable(HelenusEntity entity) {
|
||||
|
||||
if (entity.getType() != HelenusEntityType.TABLE) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.util.*;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.helenus.core.reflect.DslExportable;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
import net.helenus.mapping.HelenusEntityType;
|
||||
|
@ -185,7 +184,8 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
PackageUtil.getClasses(packageName)
|
||||
.stream()
|
||||
.filter(c -> c.isInterface() && !c.isAnnotation())
|
||||
.forEach(clazz -> {
|
||||
.forEach(
|
||||
clazz -> {
|
||||
initList.add(Either.right(clazz));
|
||||
});
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
|
@ -267,7 +267,8 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
|
||||
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
|
||||
|
||||
initList.forEach((either) -> {
|
||||
initList.forEach(
|
||||
(either) -> {
|
||||
Class<?> iface = null;
|
||||
if (either.isLeft()) {
|
||||
iface = MappingUtil.getMappingInterface(either.getLeft());
|
||||
|
@ -276,7 +277,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
}
|
||||
|
||||
DslExportable dsl = (DslExportable) Helenus.dsl(iface);
|
||||
dsl.setMetadata(session.getCluster().getMetadata());
|
||||
dsl.setCassandraMetadataForHelenusSesion(session.getCluster().getMetadata());
|
||||
sessionRepository.add(dsl);
|
||||
});
|
||||
|
||||
|
@ -286,8 +287,16 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
switch (autoDdl) {
|
||||
case CREATE_DROP:
|
||||
|
||||
// Drop tables first, otherwise a `DROP TYPE ...` will fail as the type is still referenced
|
||||
// by a table.
|
||||
// Drop view first, otherwise a `DROP TABLE ...` will fail as the type is still referenced
|
||||
// by a view.
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.VIEW)
|
||||
.forEach(e -> tableOps.dropView(e));
|
||||
|
||||
// Drop tables second, before DROP TYPE otherwise a `DROP TYPE ...` will fail as the type is
|
||||
// still referenced by a table.
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
|
@ -306,6 +315,12 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||
.forEach(e -> tableOps.createTable(e));
|
||||
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.VIEW)
|
||||
.forEach(e -> tableOps.createView(e));
|
||||
|
||||
break;
|
||||
|
||||
case VALIDATE:
|
||||
|
@ -316,16 +331,29 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
|||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||
.forEach(e -> tableOps.validateTable(getTableMetadata(e), e));
|
||||
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.updateUserType(getUserType(e), e));
|
||||
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.VIEW)
|
||||
.forEach(e -> tableOps.dropView(e));
|
||||
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||
.forEach(e -> tableOps.updateTable(getTableMetadata(e), e));
|
||||
|
||||
sessionRepository
|
||||
.entities()
|
||||
.stream()
|
||||
.filter(e -> e.getType() == HelenusEntityType.VIEW)
|
||||
.forEach(e -> tableOps.createView(e));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,11 @@ public final class TableOperations {
|
|||
}
|
||||
|
||||
public void createTable(HelenusEntity entity) {
|
||||
|
||||
sessionOps.execute(SchemaUtil.createTable(entity), true);
|
||||
|
||||
executeBatch(SchemaUtil.createIndexes(entity));
|
||||
}
|
||||
|
||||
public void dropTable(HelenusEntity entity) {
|
||||
|
||||
sessionOps.execute(SchemaUtil.dropTable(entity), true);
|
||||
}
|
||||
|
||||
|
@ -50,7 +47,10 @@ public final class TableOperations {
|
|||
|
||||
if (tmd == null) {
|
||||
throw new HelenusException(
|
||||
"table not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
|
||||
"table does not exists "
|
||||
+ entity.getName()
|
||||
+ "for entity "
|
||||
+ entity.getMappingInterface());
|
||||
}
|
||||
|
||||
List<SchemaStatement> list = SchemaUtil.alterTable(tmd, entity, dropUnusedColumns);
|
||||
|
@ -67,7 +67,31 @@ public final class TableOperations {
|
|||
}
|
||||
|
||||
public void updateTable(TableMetadata tmd, HelenusEntity entity) {
|
||||
if (tmd == null) {
|
||||
createTable(entity);
|
||||
return;
|
||||
}
|
||||
|
||||
executeBatch(SchemaUtil.alterTable(tmd, entity, dropUnusedColumns));
|
||||
executeBatch(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
|
||||
}
|
||||
|
||||
public void createView(HelenusEntity entity) {
|
||||
sessionOps.execute(
|
||||
SchemaUtil.createMaterializedView(
|
||||
sessionOps.usingKeyspace(), entity.getName().toCql(), entity),
|
||||
true);
|
||||
// executeBatch(SchemaUtil.createIndexes(entity)); NOTE: Unfortunately C* 3.10 does not yet support 2i on materialized views.
|
||||
}
|
||||
|
||||
public void dropView(HelenusEntity entity) {
|
||||
sessionOps.execute(
|
||||
SchemaUtil.dropMaterializedView(
|
||||
sessionOps.usingKeyspace(), entity.getName().toCql(), entity),
|
||||
true);
|
||||
}
|
||||
|
||||
public void updateView(TableMetadata tmd, HelenusEntity entity) {
|
||||
if (tmd == null) {
|
||||
createTable(entity);
|
||||
return;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package net.helenus.core;
|
||||
|
||||
import net.helenus.support.Either;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -41,12 +40,11 @@ public interface UnitOfWork<E extends Exception> extends AutoCloseable {
|
|||
PostCommitFunction<Void, Void> commit() throws E;
|
||||
|
||||
/**
|
||||
* Explicitly abort the work within this unit of work. Any nested aborted unit of work
|
||||
* will trigger the entire unit of work to commit.
|
||||
* Explicitly abort the work within this unit of work. Any nested aborted unit of work will
|
||||
* trigger the entire unit of work to commit.
|
||||
*/
|
||||
void abort();
|
||||
|
||||
|
||||
boolean hasAborted();
|
||||
|
||||
boolean hasCommitted();
|
||||
|
|
|
@ -23,5 +23,4 @@ class UnitOfWorkImpl extends AbstractUnitOfWork<HelenusException> {
|
|||
public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
|
||||
super(session, (AbstractUnitOfWork<HelenusException>) parent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.helenus.core.*;
|
||||
import net.helenus.mapping.HelenusProperty;
|
||||
|
||||
public abstract class AbstractFilterOptionalOperation<E, O extends AbstractFilterOptionalOperation<E, O>>
|
||||
public abstract class AbstractFilterOptionalOperation<
|
||||
E, O extends AbstractFilterOptionalOperation<E, O>>
|
||||
extends AbstractOptionalOperation<E, O> {
|
||||
|
||||
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||
|
|
|
@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.helenus.core.*;
|
||||
import net.helenus.mapping.HelenusProperty;
|
||||
|
||||
public abstract class AbstractFilterStreamOperation<E, O extends AbstractFilterStreamOperation<E, O>>
|
||||
public abstract class AbstractFilterStreamOperation<
|
||||
E, O extends AbstractFilterStreamOperation<E, O>>
|
||||
extends AbstractStreamOperation<E, O> {
|
||||
|
||||
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||
|
|
|
@ -17,8 +17,6 @@ package net.helenus.core.operation;
|
|||
|
||||
import com.codahale.metrics.Timer;
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.helenus.core.AbstractSessionOperations;
|
||||
import net.helenus.core.UnitOfWork;
|
||||
|
@ -40,7 +38,6 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
|||
return new PreparedOperation<E>(prepareStatement(), this);
|
||||
}
|
||||
|
||||
|
||||
public E sync() {
|
||||
final Timer.Context context = requestLatency.time();
|
||||
try {
|
||||
|
@ -72,5 +69,4 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
|||
if (uow == null) return async();
|
||||
return CompletableFuture.<E>supplyAsync(() -> sync(uow));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,12 +21,10 @@ import com.datastax.driver.core.ResultSet;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import net.helenus.core.AbstractSessionOperations;
|
||||
import net.helenus.core.UnitOfWork;
|
||||
|
||||
|
@ -114,5 +112,4 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
|||
if (uow == null) return async();
|
||||
return CompletableFuture.<Optional<E>>supplyAsync(() -> sync(uow));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ import net.helenus.support.HelenusException;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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> {
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
|
@ -55,7 +56,6 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
|||
this.idempotent = sessionOperations.getDefaultQueryIdempotency();
|
||||
}
|
||||
|
||||
|
||||
public O ignoreCache(boolean enabled) {
|
||||
enableCache = enabled;
|
||||
return (O) this;
|
||||
|
|
|
@ -21,20 +21,11 @@ import com.datastax.driver.core.ResultSet;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import net.helenus.core.AbstractSessionOperations;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.UnitOfWork;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
import net.helenus.mapping.value.ColumnValueProvider;
|
||||
import net.helenus.mapping.value.ValueProviderMap;
|
||||
|
||||
public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>>
|
||||
extends AbstractStatementOperation<E, O> {
|
||||
|
@ -113,5 +104,4 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
|||
if (uow == null) return async();
|
||||
return CompletableFuture.<Stream<E>>supplyAsync(() -> sync(uow));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,9 @@ public final class BoundOptionalOperation<E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public Optional<E> transform(ResultSet resultSet) { return delegate.transform(resultSet); }
|
||||
public Optional<E> transform(ResultSet resultSet) {
|
||||
return delegate.transform(resultSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement buildStatement(boolean cached) {
|
||||
|
|
|
@ -26,14 +26,17 @@ public final class BoundStreamOperation<E>
|
|||
private final BoundStatement boundStatement;
|
||||
private final AbstractStreamOperation<E, ?> delegate;
|
||||
|
||||
public BoundStreamOperation(BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
||||
public BoundStreamOperation(
|
||||
BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
||||
super(operation.sessionOps);
|
||||
this.boundStatement = boundStatement;
|
||||
this.delegate = operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
||||
public String getStatementCacheKey() {
|
||||
return delegate.getStatementCacheKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<E> transform(ResultSet resultSet) {
|
||||
|
@ -41,5 +44,7 @@ public final class BoundStreamOperation<E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public Statement buildStatement(boolean cached) { return boundStatement; }
|
||||
public Statement buildStatement(boolean cached) {
|
||||
return boundStatement;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,9 @@ import com.datastax.driver.core.ResultSet;
|
|||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||
import com.datastax.driver.core.querybuilder.Insert;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.google.common.base.Joiner;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import net.helenus.core.AbstractSessionOperations;
|
||||
import net.helenus.core.Getter;
|
||||
import net.helenus.core.Helenus;
|
||||
|
@ -41,7 +40,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
|||
|
||||
private HelenusEntity entity;
|
||||
|
||||
private final List<Fun.Tuple2<HelenusPropertyNode, Object>> values = new ArrayList<Fun.Tuple2<HelenusPropertyNode, Object>>();
|
||||
private final List<Fun.Tuple2<HelenusPropertyNode, Object>> values =
|
||||
new ArrayList<Fun.Tuple2<HelenusPropertyNode, Object>>();
|
||||
private final T pojo;
|
||||
private final Class<?> resultType;
|
||||
private boolean ifNotExists;
|
||||
|
@ -57,7 +57,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
|||
this.resultType = ResultSet.class;
|
||||
}
|
||||
|
||||
public InsertOperation(AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) {
|
||||
public InsertOperation(
|
||||
AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) {
|
||||
super(sessionOperations);
|
||||
|
||||
this.ifNotExists = ifNotExists;
|
||||
|
@ -248,7 +249,9 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
|||
|
||||
@Override
|
||||
public T sync(UnitOfWork uow) {
|
||||
if (uow == null) { return sync(); }
|
||||
if (uow == null) {
|
||||
return sync();
|
||||
}
|
||||
T result = super.sync(uow);
|
||||
Class<?> iface = entity.getMappingInterface();
|
||||
if (resultType == iface) {
|
||||
|
@ -261,5 +264,4 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
package net.helenus.core.operation;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import brave.Span;
|
||||
import brave.Tracer;
|
||||
import brave.propagation.TraceContext;
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.Timer;
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
import com.datastax.driver.core.Statement;
|
||||
|
||||
import brave.Span;
|
||||
import brave.Tracer;
|
||||
import brave.propagation.TraceContext;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import net.helenus.core.AbstractSessionOperations;
|
||||
import net.helenus.core.UnitOfWork;
|
||||
|
||||
|
||||
public abstract class Operation<E> {
|
||||
|
||||
protected final AbstractSessionOperations sessionOps;
|
||||
|
@ -31,7 +28,12 @@ public abstract class Operation<E> {
|
|||
this.requestLatency = metrics.timer("net.helenus.request-latency");
|
||||
}
|
||||
|
||||
public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, boolean showValues, boolean cached) {
|
||||
public ResultSet execute(
|
||||
AbstractSessionOperations session,
|
||||
UnitOfWork uow,
|
||||
TraceContext traceContext,
|
||||
boolean showValues,
|
||||
boolean cached) {
|
||||
|
||||
// Start recording in a Zipkin sub-span our execution time to perform this operation.
|
||||
Tracer tracer = session.getZipkinTracer();
|
||||
|
@ -60,14 +62,18 @@ public abstract class Operation<E> {
|
|||
if (span != null) {
|
||||
span.finish();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Statement options(Statement statement) { return statement; }
|
||||
|
||||
public Statement buildStatement(boolean cached) { return null; }
|
||||
|
||||
public String getStatementCacheKey() { return null; }
|
||||
|
||||
public Statement options(Statement statement) {
|
||||
return statement;
|
||||
}
|
||||
|
||||
public Statement buildStatement(boolean cached) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getStatementCacheKey() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ package net.helenus.core.operation;
|
|||
|
||||
import com.datastax.driver.core.BoundStatement;
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class PreparedStreamOperation<E> {
|
||||
|
||||
|
|
|
@ -38,7 +38,9 @@ public final class SelectFirstOperation<E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
||||
public String getStatementCacheKey() {
|
||||
return delegate.getStatementCacheKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuiltStatement buildStatement(boolean cached) {
|
||||
|
|
|
@ -36,7 +36,9 @@ public final class SelectFirstTransformingOperation<R, E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
||||
public String getStatementCacheKey() {
|
||||
return delegate.getStatementCacheKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuiltStatement buildStatement(boolean cached) {
|
||||
|
|
|
@ -23,13 +23,12 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
|
|||
import com.datastax.driver.core.querybuilder.Select;
|
||||
import com.datastax.driver.core.querybuilder.Select.Selection;
|
||||
import com.datastax.driver.core.querybuilder.Select.Where;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import net.helenus.core.*;
|
||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
|
@ -48,6 +47,7 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
|||
protected List<Ordering> ordering = null;
|
||||
protected Integer limit = null;
|
||||
protected boolean allowFiltering = false;
|
||||
protected String alternateTableName = null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public SelectOperation(AbstractSessionOperations sessionOperations) {
|
||||
|
@ -129,6 +129,19 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
|||
return new CountOperation(sessionOps, entity);
|
||||
}
|
||||
|
||||
public <V extends E> SelectOperation<E> from(Class<V> materializedViewClass) {
|
||||
Objects.requireNonNull(materializedViewClass);
|
||||
HelenusEntity entity = Helenus.entity(materializedViewClass);
|
||||
this.alternateTableName = entity.getName().toCql();
|
||||
this.allowFiltering = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectOperation<E> from(String alternateTableName) {
|
||||
this.alternateTableName = alternateTableName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectFirstOperation<E> single() {
|
||||
limit(1);
|
||||
return new SelectFirstOperation<E>(this);
|
||||
|
@ -189,7 +202,6 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
|||
switch (prop.getProperty().getColumnType()) {
|
||||
case PARTITION_KEY:
|
||||
case CLUSTERING_COLUMN:
|
||||
|
||||
Filter filter = filters.get(prop.getProperty());
|
||||
if (filter != null) {
|
||||
keys.add(filter.toString());
|
||||
|
@ -255,7 +267,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
|||
throw new HelenusMappingException("no entity or table to select data");
|
||||
}
|
||||
|
||||
Select select = selection.from(entity.getName().toCql());
|
||||
String tableName = alternateTableName == null ? entity.getName().toCql() : alternateTableName;
|
||||
Select select = selection.from(tableName);
|
||||
|
||||
if (ordering != null && !ordering.isEmpty()) {
|
||||
select.orderBy(ordering.toArray(new Ordering[ordering.size()]));
|
||||
|
@ -290,10 +303,14 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
|||
@Override
|
||||
public Stream<E> transform(ResultSet resultSet) {
|
||||
if (rowMapper != null) {
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false).map(rowMapper);
|
||||
return StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false)
|
||||
.map(rowMapper);
|
||||
} else {
|
||||
return (Stream<E>)
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),false);
|
||||
StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,9 @@ public final class SelectTransformingOperation<R, E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
||||
public String getStatementCacheKey() {
|
||||
return delegate.getStatementCacheKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuiltStatement buildStatement(boolean cached) {
|
||||
|
@ -47,5 +49,4 @@ public final class SelectTransformingOperation<R, E>
|
|||
public Stream<R> transform(ResultSet resultSet) {
|
||||
return delegate.transform(resultSet).map(fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,15 +15,13 @@
|
|||
*/
|
||||
package net.helenus.core.operation;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.querybuilder.Assignment;
|
||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Update;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import net.helenus.core.*;
|
||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
|
@ -49,13 +47,15 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
|||
this.draftMap = null;
|
||||
}
|
||||
|
||||
public UpdateOperation(AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) {
|
||||
public UpdateOperation(
|
||||
AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) {
|
||||
super(sessionOperations);
|
||||
this.draft = draft;
|
||||
this.draftMap = draft.toMap();
|
||||
}
|
||||
|
||||
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
||||
public UpdateOperation(
|
||||
AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
||||
super(sessionOperations);
|
||||
this.draft = null;
|
||||
this.draftMap = null;
|
||||
|
@ -579,7 +579,9 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
|||
|
||||
@Override
|
||||
public E sync(UnitOfWork uow) {
|
||||
if (uow == null) { return sync(); }
|
||||
if (uow == null) {
|
||||
return sync();
|
||||
}
|
||||
E result = super.sync(uow);
|
||||
if (draft != null) {
|
||||
String key = getStatementCacheKey();
|
||||
|
@ -591,5 +593,4 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.helenus.core.reflect;
|
||||
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ public interface DslExportable {
|
|||
|
||||
public static final String GET_ENTITY_METHOD = "getHelenusMappingEntity";
|
||||
public static final String GET_PARENT_METHOD = "getParentDslHelenusPropertyNode";
|
||||
public static final String SET_METADATA_METHOD = "setMetadata";
|
||||
public static final String SET_METADATA_METHOD = "setCassandraMetadataForHelenusSesion";
|
||||
|
||||
HelenusEntity getHelenusMappingEntity();
|
||||
|
||||
HelenusPropertyNode getParentDslHelenusPropertyNode();
|
||||
|
||||
void setMetadata(Metadata metadata);
|
||||
void setCassandraMetadataForHelenusSesion(Metadata metadata);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class DslInvocationHandler<E> implements InvocationHandler {
|
|||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
public void setCassandraMetadataForHelenusSesion(Metadata metadata) {
|
||||
if (metadata != null) {
|
||||
this.metadata = metadata;
|
||||
entity = init(metadata);
|
||||
|
@ -130,7 +130,7 @@ public class DslInvocationHandler<E> implements InvocationHandler {
|
|||
&& args.length == 1
|
||||
&& args[0] instanceof Metadata) {
|
||||
if (metadata == null) {
|
||||
this.setMetadata((Metadata) args[0]);
|
||||
this.setCassandraMetadataForHelenusSesion((Metadata) args[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Proxy;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.mapping.annotation.Transient;
|
||||
import net.helenus.support.HelenusException;
|
||||
|
|
|
@ -17,6 +17,7 @@ package net.helenus.mapping;
|
|||
|
||||
public enum HelenusEntityType {
|
||||
TABLE,
|
||||
VIEW,
|
||||
TUPLE,
|
||||
UDT;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
|||
}
|
||||
|
||||
for (Class<?> c : ClassUtils.getAllInterfaces(iface)) {
|
||||
if (c.getDeclaredAnnotation(Table.class) != null || c.getDeclaredAnnotation(InheritedTable.class) != null) {
|
||||
if (c.getDeclaredAnnotation(Table.class) != null
|
||||
|| c.getDeclaredAnnotation(InheritedTable.class) != null) {
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
Method o = methods.get(m.getName());
|
||||
if (o != null) {
|
||||
|
@ -145,6 +146,9 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
|||
case TABLE:
|
||||
return MappingUtil.getTableName(iface, true);
|
||||
|
||||
case VIEW:
|
||||
return MappingUtil.getViewName(iface, true);
|
||||
|
||||
case TUPLE:
|
||||
return IdentityName.of(MappingUtil.getDefaultEntityName(iface), false);
|
||||
|
||||
|
@ -161,6 +165,8 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
|||
|
||||
if (null != iface.getDeclaredAnnotation(Table.class)) {
|
||||
return HelenusEntityType.TABLE;
|
||||
} else if (null != iface.getDeclaredAnnotation(MaterializedView.class)) {
|
||||
return HelenusEntityType.VIEW;
|
||||
} else if (null != iface.getDeclaredAnnotation(Tuple.class)) {
|
||||
return HelenusEntityType.TUPLE;
|
||||
} else if (null != iface.getDeclaredAnnotation(UDT.class)) {
|
||||
|
|
|
@ -25,10 +25,7 @@ import javax.validation.ConstraintValidator;
|
|||
import net.helenus.core.Getter;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.reflect.*;
|
||||
import net.helenus.mapping.annotation.Index;
|
||||
import net.helenus.mapping.annotation.Table;
|
||||
import net.helenus.mapping.annotation.Tuple;
|
||||
import net.helenus.mapping.annotation.UDT;
|
||||
import net.helenus.mapping.annotation.*;
|
||||
import net.helenus.support.DslPropertyException;
|
||||
import net.helenus.support.HelenusMappingException;
|
||||
|
||||
|
@ -172,6 +169,28 @@ public final class MappingUtil {
|
|||
return udt != null;
|
||||
}
|
||||
|
||||
public static IdentityName getViewName(Class<?> iface, boolean required) {
|
||||
|
||||
String viewName = null;
|
||||
boolean forceQuote = false;
|
||||
|
||||
MaterializedView view = iface.getDeclaredAnnotation(MaterializedView.class);
|
||||
|
||||
if (view != null) {
|
||||
viewName = view.value();
|
||||
forceQuote = view.forceQuote();
|
||||
|
||||
} else if (required) {
|
||||
throw new HelenusMappingException("entity must have annotation @Table " + iface);
|
||||
}
|
||||
|
||||
if (viewName == null || viewName.isEmpty()) {
|
||||
viewName = getDefaultEntityName(iface);
|
||||
}
|
||||
|
||||
return new IdentityName(viewName, forceQuote);
|
||||
}
|
||||
|
||||
public static IdentityName getTableName(Class<?> iface, boolean required) {
|
||||
|
||||
String tableName = null;
|
||||
|
@ -222,6 +241,7 @@ public final class MappingUtil {
|
|||
}
|
||||
|
||||
if (iface.getDeclaredAnnotation(Table.class) != null
|
||||
|| iface.getDeclaredAnnotation(MaterializedView.class) != null
|
||||
|| iface.getDeclaredAnnotation(UDT.class) != null
|
||||
|| iface.getDeclaredAnnotation(Tuple.class) != null) {
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package net.helenus.mapping.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* CoveringIndex annotation is using under the specific column or method in entity interface
|
||||
* with @Table annotation.
|
||||
*
|
||||
* <p>A corresponding materialized view will be created based on the underline @Table for the
|
||||
* specific column.
|
||||
*
|
||||
* <p>This is useful when you need to perform IN or SORT/ORDER-BY queries and to do so you'll need
|
||||
* different materialized table on disk in Cassandra.
|
||||
*
|
||||
* <p>For each @Table annotated interface Helenus will create/update/verify Cassandra Materialized
|
||||
* Views and some indexes if needed on startup.
|
||||
*/
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface CoveringIndex {
|
||||
|
||||
/**
|
||||
* Defined the name of the index. By default the entity name with column name as suffix.
|
||||
*
|
||||
* @return name of the covering index
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* Set of fields in this entity to replicate in the index.
|
||||
*
|
||||
* @return array of the string names of the fields.
|
||||
*/
|
||||
String[] covering() default "";
|
||||
|
||||
/**
|
||||
* Set of fields to use as the partition keys for this projection.
|
||||
*
|
||||
* @return array of the string names of the fields.
|
||||
*/
|
||||
String[] partitionKeys() default "";
|
||||
|
||||
/**
|
||||
* Set of fields to use as the clustering columns for this projection.
|
||||
*
|
||||
* @return array of the string names of the fields.
|
||||
*/
|
||||
String[] clusteringColumns() default "";
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Materialized alternate view of another Entity annotation
|
||||
*
|
||||
* <p>MaterializedView annotation is used to define different mapping to some other Table interface
|
||||
*
|
||||
* <p>This is useful when you need to perform IN or SORT/ORDER-BY queries and to do so you'll need
|
||||
* different materialized table on disk in Cassandra.
|
||||
*
|
||||
* <p>For each @Table annotated interface Helenus will create/update/verify Cassandra Materialized
|
||||
* Views and some indexes if needed on startup.
|
||||
*/
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface MaterializedView {
|
||||
|
||||
/**
|
||||
* Default value is the SimpleName of the interface normalized to underscore
|
||||
*
|
||||
* @return name of the type
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||
* name of the type needs to be quoted.
|
||||
*
|
||||
* <p>Default value is false, we are quoting only selected names.
|
||||
*
|
||||
* @return true if name have to be quoted
|
||||
*/
|
||||
boolean forceQuote() default false;
|
||||
}
|
|
@ -2,6 +2,7 @@ package net.helenus.mapping.javatype;
|
|||
|
||||
public abstract class AbstractCollectionJavaType extends AbstractJavaType {
|
||||
|
||||
public static boolean isCollectionType() { return true; }
|
||||
|
||||
public static boolean isCollectionType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,9 @@ import net.helenus.support.HelenusMappingException;
|
|||
|
||||
public abstract class AbstractJavaType {
|
||||
|
||||
public static boolean isCollectionType() { return false; }
|
||||
public static boolean isCollectionType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract Class<?> getJavaClass();
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ package net.helenus.mapping.javatype;
|
|||
import com.datastax.driver.core.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
|
|
@ -8,6 +8,7 @@ public abstract class AbstractCollectionDataType extends AbstractDataType {
|
|||
super(columnType);
|
||||
}
|
||||
|
||||
public boolean isCollectionType() { return true; }
|
||||
|
||||
public boolean isCollectionType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public abstract class AbstractDataType {
|
|||
"wrong column type " + columnType + " for UserDefinedType in columnName " + columnName);
|
||||
}
|
||||
|
||||
public boolean isCollectionType() { return false; }
|
||||
|
||||
public boolean isCollectionType() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ package net.helenus.mapping.type;
|
|||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.UserType;
|
||||
import com.datastax.driver.core.schemabuilder.*;
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.List;
|
||||
import net.helenus.mapping.ColumnType;
|
||||
import net.helenus.mapping.IdentityName;
|
||||
|
|
|
@ -67,11 +67,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
// read full object
|
||||
|
||||
Customer actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
Customer actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(aliases, actual.aliases());
|
||||
Assert.assertNull(actual.names());
|
||||
|
@ -90,11 +87,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
|
||||
|
||||
actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(expected, actual.aliases());
|
||||
|
@ -170,11 +164,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
// read full object
|
||||
|
||||
Customer actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
Customer actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(names, actual.names());
|
||||
|
@ -200,11 +191,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
|
||||
|
||||
actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(expected, actual.names());
|
||||
|
@ -306,10 +294,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
// read full object
|
||||
|
||||
Customer actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id)).single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
Customer actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(props, actual.properties());
|
||||
|
@ -343,11 +329,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
|
||||
|
||||
actual = session.<Customer>select(customer)
|
||||
.where(customer::id, eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
actual =
|
||||
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||
Assert.assertEquals(id, actual.id());
|
||||
Assert.assertEquals(expected, actual.properties());
|
||||
|
||||
|
|
|
@ -18,31 +18,21 @@ package net.helenus.test.integration.core.draft;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.HelenusSession;
|
||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
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 {
|
||||
|
||||
|
||||
static Supply supply;
|
||||
static HelenusSession session;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTest() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -50,44 +40,50 @@ public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
|
|||
public void testFoo() throws Exception {
|
||||
Supply.Draft draft = null;
|
||||
|
||||
draft = Supply.draft("APAC")
|
||||
draft =
|
||||
Supply.draft("APAC")
|
||||
.code("WIDGET-002")
|
||||
.description("Our second Widget!")
|
||||
.demand(new HashMap<String, Long>() {{
|
||||
.demand(
|
||||
new HashMap<String, Long>() {
|
||||
{
|
||||
put("APAC", 100L);
|
||||
put("EMEA", 10000L);
|
||||
put("NORAM", 2000000L);
|
||||
}})
|
||||
.shipments(new HashSet<String>() {{
|
||||
}
|
||||
})
|
||||
.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>() {{
|
||||
}
|
||||
})
|
||||
.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
|
||||
Supply s2 = session.<Supply>update(s1.update())
|
||||
Supply s2 =
|
||||
session
|
||||
.<Supply>update(s1.update())
|
||||
.prepend(supply::suppliers, "Pignose Supply, LLC.")
|
||||
.sync();
|
||||
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();
|
||||
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();
|
||||
Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
|
||||
Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,40 @@
|
|||
package net.helenus.test.integration.core.draft;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import net.helenus.core.AbstractAuditedEntityDraft;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.reflect.MapExportable;
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
|
||||
@Table
|
||||
public interface Inventory {
|
||||
|
||||
static Inventory inventory = Helenus.dsl(Inventory.class);
|
||||
|
||||
@PartitionKey UUID id();
|
||||
@Column("emea") @Types.Counter long EMEA();
|
||||
@Column("noram") @Types.Counter long NORAM();
|
||||
@Column("apac") @Types.Counter long APAC();
|
||||
@PartitionKey
|
||||
UUID id();
|
||||
|
||||
@Transient static Draft draft(UUID id) { return new Draft(id); }
|
||||
@Column("emea")
|
||||
@Types.Counter
|
||||
long EMEA();
|
||||
|
||||
@Transient default Draft update() { return new Draft(this); }
|
||||
@Column("noram")
|
||||
@Types.Counter
|
||||
long NORAM();
|
||||
|
||||
@Column("apac")
|
||||
@Types.Counter
|
||||
long APAC();
|
||||
|
||||
@Transient
|
||||
static Draft draft(UUID id) {
|
||||
return new Draft(id);
|
||||
}
|
||||
|
||||
@Transient
|
||||
default Draft update() {
|
||||
return new Draft(this);
|
||||
}
|
||||
|
||||
class Draft extends AbstractAuditedEntityDraft<Inventory> {
|
||||
|
||||
|
@ -37,9 +50,13 @@ public interface Inventory {
|
|||
super((MapExportable) inventory);
|
||||
}
|
||||
|
||||
public Class<Inventory> getEntityClass() { return Inventory.class; }
|
||||
public Class<Inventory> getEntityClass() {
|
||||
return Inventory.class;
|
||||
}
|
||||
|
||||
protected String getCurrentAuditor() { return "unknown"; }
|
||||
protected String getCurrentAuditor() {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
// Immutable properties:
|
||||
public UUID id() {
|
||||
|
@ -72,7 +89,5 @@ public interface Inventory {
|
|||
mutate(inventory::NORAM, count);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +1,52 @@
|
|||
package net.helenus.test.integration.core.draft;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import com.datastax.driver.core.utils.UUIDs;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.datastax.driver.core.utils.UUIDs;
|
||||
|
||||
import net.helenus.core.AbstractEntityDraft;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.reflect.MapExportable;
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
|
||||
@Table
|
||||
public interface Supply {
|
||||
|
||||
static Supply supply = Helenus.dsl(Supply.class);
|
||||
|
||||
@PartitionKey UUID id();
|
||||
@ClusteringColumn(ordinal=0) default String region() { return "NORAM"; }
|
||||
@PartitionKey
|
||||
UUID id();
|
||||
|
||||
@Index(caseSensitive = false) String code();
|
||||
@Index String description(); // @IndexText == lucene index
|
||||
@Index Map<String, Long> demand();
|
||||
@Index List<String> suppliers();
|
||||
@Index Set<String> shipments();
|
||||
@ClusteringColumn(ordinal = 0)
|
||||
default String region() {
|
||||
return "NORAM";
|
||||
}
|
||||
|
||||
@Transient static Draft draft(String region) { return new Draft(region); }
|
||||
@Index(caseSensitive = false)
|
||||
String code();
|
||||
|
||||
@Transient default Draft update() { return new Draft(this); }
|
||||
@Index
|
||||
String description(); // @IndexText == lucene index
|
||||
|
||||
@Index
|
||||
Map<String, Long> demand();
|
||||
|
||||
@Index
|
||||
List<String> suppliers();
|
||||
|
||||
@Index
|
||||
Set<String> shipments();
|
||||
|
||||
@Transient
|
||||
static Draft draft(String region) {
|
||||
return new Draft(region);
|
||||
}
|
||||
|
||||
@Transient
|
||||
default Draft update() {
|
||||
return new Draft(this);
|
||||
}
|
||||
|
||||
class Draft extends AbstractEntityDraft<Supply> {
|
||||
|
||||
|
@ -48,7 +63,9 @@ public interface Supply {
|
|||
super((MapExportable) supply);
|
||||
}
|
||||
|
||||
public Class<Supply> getEntityClass() { return Supply.class; }
|
||||
public Class<Supply> getEntityClass() {
|
||||
return Supply.class;
|
||||
}
|
||||
|
||||
// Immutable properties:
|
||||
public UUID id() {
|
||||
|
@ -124,6 +141,5 @@ public interface Supply {
|
|||
public Draft setshipments(Set<String> shipments) {
|
||||
return shipments(shipments);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
|
|||
.value(cat::nickname, "garfield")
|
||||
.value(cat::eatable, false)
|
||||
.sync();
|
||||
Optional<Cat> animal = session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
|
||||
Optional<Cat> animal =
|
||||
session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
|
||||
Assert.assertTrue(animal.isPresent());
|
||||
|
||||
Cat cat = animal.get();
|
||||
|
|
|
@ -20,6 +20,7 @@ import net.helenus.mapping.annotation.InheritedTable;
|
|||
@InheritedTable
|
||||
public interface Mammal extends Animal {
|
||||
|
||||
default boolean warmBlodded() { return true; }
|
||||
|
||||
default boolean warmBlodded() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,21 +18,17 @@ package net.helenus.test.integration.core.simple;
|
|||
import static net.helenus.core.Query.eq;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import java.util.*;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.HelenusSession;
|
||||
import net.helenus.core.Operator;
|
||||
import net.helenus.core.operation.UpdateOperation;
|
||||
import net.helenus.core.reflect.Drafted;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
import net.helenus.support.Fun;
|
||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||
|
||||
static User user;
|
||||
|
@ -102,11 +98,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
// select as object
|
||||
|
||||
actual = session.<User>select(user)
|
||||
.where(user::id, eq(100L))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||
assertUsers(newUser, actual);
|
||||
|
||||
// select by columns
|
||||
|
@ -192,11 +184,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
Assert.assertEquals("_albert", name);
|
||||
|
||||
User u2 = session.<User>select(user)
|
||||
.where(user::id, eq(100L))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(100L), u2.id());
|
||||
Assert.assertEquals("albert", u2.name());
|
||||
|
@ -213,11 +201,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
|||
.sync();
|
||||
|
||||
Optional<User> maybeGreg =
|
||||
session
|
||||
.<User>select(user)
|
||||
.where(user::id, eq(1234L))
|
||||
.single()
|
||||
.sync();
|
||||
session.<User>select(user).where(user::id, eq(1234L)).single().sync();
|
||||
|
||||
// INSERT
|
||||
|
||||
|
@ -260,13 +244,8 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
|||
.zipkinContext(null)
|
||||
.sync();
|
||||
|
||||
|
||||
UpdateOperation<ResultSet> update = session.update();
|
||||
update
|
||||
.set(user::name, null)
|
||||
.zipkinContext(null)
|
||||
.sync();
|
||||
|
||||
update.set(user::name, null).zipkinContext(null).sync();
|
||||
}
|
||||
|
||||
private void assertUsers(User expected, User actual) {
|
||||
|
|
|
@ -42,11 +42,8 @@ public class TupleMapTest extends TupleCollectionTest {
|
|||
|
||||
// read full object
|
||||
|
||||
Book actual = session.<Book>select(book)
|
||||
.where(book::id, Query.eq(id))
|
||||
.single()
|
||||
.sync()
|
||||
.orElse(null);
|
||||
Book actual =
|
||||
session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
||||
Assert.assertEquals(id, actual.id());
|
||||
assertEqualMaps(writers, actual.writers());
|
||||
Assert.assertNull(actual.reviewers());
|
||||
|
@ -77,11 +74,7 @@ public class TupleMapTest extends TupleCollectionTest {
|
|||
|
||||
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());
|
||||
assertEqualMaps(expected, actual.writers());
|
||||
|
@ -96,7 +89,8 @@ public class TupleMapTest extends TupleCollectionTest {
|
|||
expected.put(third, unk);
|
||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||
|
||||
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||
actualMap =
|
||||
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
|
||||
assertEqualMaps(expected, actualMap);
|
||||
|
||||
// putAll operation
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package net.helenus.test.integration.core.unitofwork;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.HelenusSession;
|
||||
import net.helenus.core.UnitOfWork;
|
||||
|
@ -23,21 +26,13 @@ import org.junit.Assert;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
||||
|
||||
static HelenusSession session;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTest() {
|
||||
session = Helenus.init(getSession())
|
||||
.showCql()
|
||||
.autoCreateDrop()
|
||||
.get();
|
||||
session = Helenus.init(getSession()).showCql().autoCreateDrop().get();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -48,17 +43,37 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
|||
uow5 = session.begin();
|
||||
uow3 = session.begin(uow5);
|
||||
uow1 = session.begin(uow3);
|
||||
uow1.commit().andThen(() -> { q.add("1"); });
|
||||
uow1.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("1");
|
||||
});
|
||||
uow2 = session.begin(uow3);
|
||||
uow2.commit().andThen(() -> { q.add("2"); });
|
||||
uow3.commit().andThen(() -> { q.add("3"); });
|
||||
uow2.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("2");
|
||||
});
|
||||
uow3.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("3");
|
||||
});
|
||||
uow4 = session.begin(uow5);
|
||||
uow4.commit().andThen(() -> { q.add("4"); });
|
||||
uow5.commit().andThen(() -> { q.add("5"); });
|
||||
uow4.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("4");
|
||||
});
|
||||
uow5.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("5");
|
||||
});
|
||||
|
||||
System.out.println(q);
|
||||
Assert.assertTrue(Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"}));
|
||||
|
||||
Assert.assertTrue(
|
||||
Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"}));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -71,28 +86,39 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
|||
try {
|
||||
uow3 = session.begin(uow4);
|
||||
uow1 = session.begin(uow3);
|
||||
uow1.commit().andThen(() -> {
|
||||
uow1.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("1");
|
||||
});
|
||||
uow2 = session.begin(uow3);
|
||||
uow2.commit().andThen(() -> {
|
||||
uow2.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("2");
|
||||
});
|
||||
uow3.commit().andThen(() -> {
|
||||
uow3.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("3");
|
||||
});
|
||||
uow4.commit().andThen(() -> {
|
||||
uow4.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("4");
|
||||
});
|
||||
throw new Exception();
|
||||
} catch (Exception e) {
|
||||
uow4.abort();
|
||||
}
|
||||
uow5.commit().andThen(() -> { q.add("5"); });
|
||||
uow5.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
q.add("5");
|
||||
});
|
||||
|
||||
System.out.println(q);
|
||||
Assert.assertTrue(q.isEmpty() == true);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -103,7 +129,6 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
|||
Assert.assertFalse(uow.hasAborted());
|
||||
}
|
||||
Assert.assertTrue(unitOfWork.hasAborted());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -112,7 +137,9 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
|||
try (UnitOfWork uow = session.begin()) {
|
||||
unitOfWork = uow;
|
||||
Assert.assertFalse(uow.hasAborted());
|
||||
uow.commit().andThen(() -> {
|
||||
uow.commit()
|
||||
.andThen(
|
||||
() -> {
|
||||
Assert.assertFalse(uow.hasAborted());
|
||||
Assert.assertTrue(uow.hasCommitted());
|
||||
});
|
||||
|
@ -120,5 +147,4 @@ public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
|||
Assert.assertFalse(unitOfWork.hasAborted());
|
||||
Assert.assertTrue(unitOfWork.hasCommitted());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,13 @@
|
|||
*/
|
||||
package net.helenus.test.integration.core.unitofwork;
|
||||
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
import com.datastax.driver.core.DataType.Name;
|
||||
import java.util.Set;
|
||||
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
@UDT
|
||||
public interface Directory extends FilesystemNode {
|
||||
|
||||
@Types.Set(Name.TIMEUUID)
|
||||
Set<FilesystemNode> inodes();
|
||||
|
||||
}
|
||||
|
|
|
@ -17,11 +17,9 @@ package net.helenus.test.integration.core.unitofwork;
|
|||
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
|
||||
@UDT
|
||||
public interface File extends FilesystemNode {
|
||||
|
||||
@Column
|
||||
byte[] data();
|
||||
|
||||
}
|
||||
|
|
|
@ -21,5 +21,4 @@ import net.helenus.mapping.annotation.UDT;
|
|||
public interface FileAttributes {
|
||||
|
||||
String owner();
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
*/
|
||||
package net.helenus.test.integration.core.unitofwork;
|
||||
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
@Table("fs")
|
||||
public interface FilesystemNode {
|
||||
|
@ -30,5 +29,4 @@ public interface FilesystemNode {
|
|||
|
||||
@Column
|
||||
FileAttributes attr();
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
*/
|
||||
package net.helenus.test.integration.core.unitofwork;
|
||||
|
||||
import static net.helenus.core.Query.eq;
|
||||
|
||||
import com.datastax.driver.core.utils.UUIDs;
|
||||
import java.util.UUID;
|
||||
import net.bytebuddy.utility.RandomString;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.HelenusSession;
|
||||
|
@ -29,34 +32,24 @@ import org.junit.Assert;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.helenus.core.Query.eq;
|
||||
|
||||
|
||||
@Table
|
||||
@Cacheable
|
||||
interface Widget {
|
||||
@PartitionKey
|
||||
UUID id();
|
||||
|
||||
@Column
|
||||
String name();
|
||||
}
|
||||
|
||||
|
||||
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
||||
|
||||
static Widget widget;
|
||||
static HelenusSession session;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -66,7 +59,8 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
|||
UUID key = UUIDs.timeBased();
|
||||
|
||||
// This should inserted Widget, but not cache it.
|
||||
session.<Widget>insert(widget)
|
||||
session
|
||||
.<Widget>insert(widget)
|
||||
.value(widget::id, key)
|
||||
.value(widget::name, RandomString.make(20))
|
||||
.sync();
|
||||
|
@ -74,25 +68,19 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
|||
try (UnitOfWork uow = session.begin()) {
|
||||
|
||||
// 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);
|
||||
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::id, eq(key))
|
||||
.single()
|
||||
.sync(uow)
|
||||
.orElse(null);
|
||||
w2 =
|
||||
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||
|
||||
uow.commit()
|
||||
.andThen(() -> {
|
||||
.andThen(
|
||||
() -> {
|
||||
Assert.assertEquals(w1, w2);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -103,7 +91,9 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
// This should inserted Widget, and not cache it in uow1.
|
||||
try (UnitOfWork uow1 = session.begin()) {
|
||||
w1 = session.<Widget>insert(widget)
|
||||
w1 =
|
||||
session
|
||||
.<Widget>insert(widget)
|
||||
.value(widget::id, key1)
|
||||
.value(widget::name, RandomString.make(20))
|
||||
.sync(uow1);
|
||||
|
@ -111,7 +101,9 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
|||
try (UnitOfWork uow2 = session.begin(uow1)) {
|
||||
|
||||
// This should read from uow1's cache and return the same Widget.
|
||||
w2 = session.<Widget>select(widget)
|
||||
w2 =
|
||||
session
|
||||
.<Widget>select(widget)
|
||||
.where(widget::id, eq(key1))
|
||||
.single()
|
||||
.sync(uow2)
|
||||
|
@ -119,30 +111,35 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
|||
|
||||
Assert.assertEquals(w1, w2);
|
||||
|
||||
w3 = session.<Widget>insert(widget)
|
||||
w3 =
|
||||
session
|
||||
.<Widget>insert(widget)
|
||||
.value(widget::id, key2)
|
||||
.value(widget::name, RandomString.make(20))
|
||||
.sync(uow2);
|
||||
|
||||
uow2.commit()
|
||||
.andThen(() -> {
|
||||
.andThen(
|
||||
() -> {
|
||||
Assert.assertEquals(w1, w2);
|
||||
});
|
||||
}
|
||||
|
||||
// This should read from the cache and get the same instance of a Widget.
|
||||
w4 = session.<Widget>select(widget)
|
||||
w4 =
|
||||
session
|
||||
.<Widget>select(widget)
|
||||
.where(widget::id, eq(key2))
|
||||
.single()
|
||||
.sync(uow1)
|
||||
.orElse(null);
|
||||
|
||||
uow1.commit()
|
||||
.andThen(() -> {
|
||||
.andThen(
|
||||
() -> {
|
||||
Assert.assertEquals(w3, w4);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package net.helenus.test.integration.core.views;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import net.helenus.mapping.annotation.ClusteringColumn;
|
||||
import net.helenus.mapping.annotation.CoveringIndex;
|
||||
import net.helenus.mapping.annotation.PartitionKey;
|
||||
import net.helenus.mapping.annotation.Table;
|
||||
|
||||
@Table
|
||||
@CoveringIndex(
|
||||
name = "cyclist_mv",
|
||||
covering = {"age", "birthday", "country"},
|
||||
partitionKeys = {"age", "cid"},
|
||||
clusteringColumns = {}
|
||||
)
|
||||
public interface Cyclist {
|
||||
@ClusteringColumn
|
||||
UUID cid();
|
||||
|
||||
String name();
|
||||
|
||||
@PartitionKey
|
||||
int age();
|
||||
|
||||
Date birthday();
|
||||
|
||||
String country();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package net.helenus.test.integration.core.views;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
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
|
||||
public interface CyclistsByAge extends Cyclist {
|
||||
@PartitionKey
|
||||
UUID cid();
|
||||
|
||||
@ClusteringColumn
|
||||
int age();
|
||||
|
||||
Date birthday();
|
||||
|
||||
@Index
|
||||
String country();
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.test.integration.core.views;
|
||||
|
||||
import static net.helenus.core.Query.eq;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import net.helenus.core.Helenus;
|
||||
import net.helenus.core.HelenusSession;
|
||||
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
|
||||
// https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateMaterializedView.html
|
||||
// https://www.datastax.com/dev/blog/materialized-view-performance-in-cassandra-3-x
|
||||
public class MaterializedViewTest extends AbstractEmbeddedCassandraTest {
|
||||
|
||||
static Cyclist cyclist;
|
||||
static HelenusSession session;
|
||||
|
||||
static Date dateFromString(String dateInString) {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
|
||||
try {
|
||||
return formatter.parse(dateInString);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTest() {
|
||||
session =
|
||||
Helenus.init(getSession())
|
||||
.showCql()
|
||||
.add(Cyclist.class)
|
||||
.add(CyclistsByAge.class)
|
||||
.autoCreateDrop()
|
||||
.get();
|
||||
cyclist = session.dsl(Cyclist.class);
|
||||
|
||||
session
|
||||
.insert(cyclist)
|
||||
.value(cyclist::cid, UUID.randomUUID())
|
||||
.value(cyclist::age, 18)
|
||||
.value(cyclist::birthday, dateFromString("1997-02-08"))
|
||||
.value(cyclist::country, "Netherlands")
|
||||
.value(cyclist::name, "Pascal EENKHOORN")
|
||||
.sync();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMv() throws Exception {
|
||||
session
|
||||
.select(Cyclist.class)
|
||||
.<CyclistsByAge>from(CyclistsByAge.class)
|
||||
.where(cyclist::age, eq(18))
|
||||
.sync();
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.helenus.core.reflect.Drafted;
|
||||
import net.helenus.mapping.HelenusEntity;
|
||||
import net.helenus.mapping.annotation.*;
|
||||
|
||||
@Table
|
||||
|
|
Loading…
Reference in a new issue