WIP: More work toward entity cache, very broken at this point.
This commit is contained in:
parent
cb09324ac6
commit
1b46ee0ed1
41 changed files with 332 additions and 203 deletions
2
pom.xml
2
pom.xml
|
@ -5,7 +5,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>net.helenus</groupId>
|
<groupId>net.helenus</groupId>
|
||||||
<artifactId>helenus-core</artifactId>
|
<artifactId>helenus-core</artifactId>
|
||||||
<version>2.0.26-SNAPSHOT</version>
|
<version>2.0.27-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>helenus</name>
|
<name>helenus</name>
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.diffplug.common.base.Errors;
|
import com.diffplug.common.base.Errors;
|
||||||
import com.google.common.collect.TreeTraverser;
|
import com.google.common.collect.TreeTraverser;
|
||||||
import net.helenus.core.operation.AbstractCache;
|
import net.helenus.core.operation.AbstractCache;
|
||||||
|
import net.helenus.core.operation.CacheKey;
|
||||||
import net.helenus.core.operation.UnitOfWorkCache;
|
import net.helenus.core.operation.UnitOfWorkCache;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ public final class UnitOfWork implements AutoCloseable {
|
||||||
private final HelenusSession session;
|
private final HelenusSession session;
|
||||||
private final UnitOfWork parent;
|
private final UnitOfWork parent;
|
||||||
private List<CommitThunk> postCommit = new ArrayList<CommitThunk>();
|
private List<CommitThunk> postCommit = new ArrayList<CommitThunk>();
|
||||||
|
private final Map<CacheKey, ResultSet> cache = new HashMap<>();
|
||||||
private boolean aborted = false;
|
private boolean aborted = false;
|
||||||
private boolean committed = false;
|
private boolean committed = false;
|
||||||
|
|
||||||
|
@ -56,6 +59,10 @@ public final class UnitOfWork implements AutoCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UnitOfWork getEnclosingUnitOfWork() { return parent; }
|
||||||
|
|
||||||
|
public Map<CacheKey, ResultSet> getCache() { return cache; }
|
||||||
|
|
||||||
private Iterator<UnitOfWork> getChildNodes() {
|
private Iterator<UnitOfWork> getChildNodes() {
|
||||||
return nested.iterator();
|
return nested.iterator();
|
||||||
}
|
}
|
||||||
|
@ -85,6 +92,8 @@ public final class UnitOfWork implements AutoCloseable {
|
||||||
committed = true;
|
committed = true;
|
||||||
aborted = false;
|
aborted = false;
|
||||||
|
|
||||||
|
// TODO(gburd): union this cache with parent's (if there is a parent) or with the session cache for all cacheable entities we currently hold
|
||||||
|
|
||||||
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
||||||
|
|
||||||
// Apply all post-commit functions for
|
// Apply all post-commit functions for
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public abstract class AbstractCache<K, V> {
|
public abstract class AbstractCache<K, V> {
|
||||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
protected Cache<K, V> cache;
|
public Cache<K, V> cache;
|
||||||
|
|
||||||
public AbstractCache() {
|
public AbstractCache() {
|
||||||
RemovalListener<K, V> listener =
|
RemovalListener<K, V> listener =
|
||||||
|
@ -38,8 +38,11 @@ public abstract class AbstractCache<K, V> {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ResultSet apply(
|
V get(K key) {
|
||||||
Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
return cache.getIfPresent(key);
|
||||||
throws InterruptedException, ExecutionException;
|
}
|
||||||
|
|
||||||
|
void put(K key, V value) {
|
||||||
|
cache.put(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public abstract class AbstractFilterOptionalOperation<
|
public abstract class AbstractFilterOptionalOperation<
|
||||||
E, O extends AbstractFilterOptionalOperation<E, O>>
|
E, O extends AbstractFilterOptionalOperation<E, O>>
|
||||||
extends AbstractOptionalOperation<E, O> {
|
extends AbstractOptionalOperation<E, O> {
|
||||||
|
|
||||||
protected List<Filter<?>> filters = null;
|
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||||
protected List<Filter<?>> ifFilters = null;
|
protected List<Filter<?>> ifFilters = null;
|
||||||
|
|
||||||
public AbstractFilterOptionalOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractFilterOptionalOperation(AbstractSessionOperations sessionOperations) {
|
||||||
|
@ -95,9 +99,9 @@ public abstract class AbstractFilterOptionalOperation<
|
||||||
|
|
||||||
private void addFilter(Filter<?> filter) {
|
private void addFilter(Filter<?> filter) {
|
||||||
if (filters == null) {
|
if (filters == null) {
|
||||||
filters = new LinkedList<Filter<?>>();
|
filters = new LinkedHashMap<HelenusProperty, Filter<?>>();
|
||||||
}
|
}
|
||||||
filters.add(filter);
|
filters.put(filter.getNode().getProperty(), filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIfFilter(Filter<?> filter) {
|
private void addIfFilter(Filter<?> filter) {
|
||||||
|
|
|
@ -15,15 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public abstract class AbstractFilterStreamOperation<
|
public abstract class AbstractFilterStreamOperation<
|
||||||
E, O extends AbstractFilterStreamOperation<E, O>>
|
E, O extends AbstractFilterStreamOperation<E, O>>
|
||||||
extends AbstractStreamOperation<E, O> {
|
extends AbstractStreamOperation<E, O> {
|
||||||
|
|
||||||
protected List<Filter<?>> filters = null;
|
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||||
protected List<Filter<?>> ifFilters = null;
|
protected List<Filter<?>> ifFilters = null;
|
||||||
|
|
||||||
public AbstractFilterStreamOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractFilterStreamOperation(AbstractSessionOperations sessionOperations) {
|
||||||
|
@ -95,9 +99,9 @@ public abstract class AbstractFilterStreamOperation<
|
||||||
|
|
||||||
private void addFilter(Filter<?> filter) {
|
private void addFilter(Filter<?> filter) {
|
||||||
if (filters == null) {
|
if (filters == null) {
|
||||||
filters = new LinkedList<Filter<?>>();
|
filters = new LinkedHashMap<HelenusProperty, Filter<?>>();
|
||||||
}
|
}
|
||||||
filters.add(filter);
|
filters.put(filter.getNode().getProperty(), filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIfFilter(Filter<?> filter) {
|
private void addIfFilter(Filter<?> filter) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
||||||
|
|
||||||
public abstract E transform(ResultSet resultSet);
|
public abstract E transform(ResultSet resultSet);
|
||||||
|
|
||||||
protected AbstractCache getCache() {
|
public AbstractCache getCache() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,21 +46,19 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
||||||
}
|
}
|
||||||
|
|
||||||
public E sync() {
|
public E sync() {
|
||||||
return Executioner.INSTANCE.<E>sync(
|
return Executioner.INSTANCE.<E>sync(sessionOps, null, traceContext, this, showValues);
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
public E sync(UnitOfWork uow) {
|
public E sync(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<E>sync(
|
return Executioner.INSTANCE.<E>sync(sessionOps, uow, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<E> async() {
|
public CompletableFuture<E> async() {
|
||||||
return Executioner.INSTANCE.<E>async(
|
AbstractCache cache = getCache();
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
boolean cacheResult = cache != null;
|
||||||
|
return Executioner.INSTANCE.<E>async(sessionOps, null, traceContext, this, showValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<E> async(UnitOfWork uow) {
|
public CompletableFuture<E> async(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<E>async(
|
return Executioner.INSTANCE.<E>async(sessionOps, uow, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,22 @@ import net.helenus.core.UnitOfWork;
|
||||||
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> implements OperationsDelegate<Optional<E>> {
|
extends AbstractStatementOperation<E, O> implements OperationsDelegate<Optional<E>> {
|
||||||
|
|
||||||
|
private Function<Optional<E>, E> extractor = new Function<Optional<E>, E>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E apply(Optional<E> e) {
|
||||||
|
return e.orElse(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Optional<E> transform(ResultSet resultSet);
|
public abstract Optional<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
protected AbstractCache getCache() { return null; }
|
public AbstractCache getCache() { return null; }
|
||||||
|
|
||||||
public CacheKey getCacheKey() {
|
public CacheKey getCacheKey() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -57,23 +66,19 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<E> sync() {
|
public Optional<E> sync() {
|
||||||
return Executioner.INSTANCE.<Optional<E>>sync(
|
return Executioner.INSTANCE.<Optional<E>>sync(sessionOps, null, extractor, traceContext, this, showValues);
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<E> sync(UnitOfWork uow) {
|
public Optional<E> sync(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<Optional<E>>sync(
|
return Executioner.INSTANCE.<Optional<E>>sync(sessionOps, uow, extractor, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Optional<E>> async() {
|
public CompletableFuture<Optional<E>> async() {
|
||||||
return Executioner.INSTANCE.<Optional<E>>async(
|
return Executioner.INSTANCE.<Optional<E>>async(sessionOps, null, extractor, traceContext, this, showValues);
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Optional<E>> async(UnitOfWork uow) {
|
public CompletableFuture<Optional<E>> async(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<Optional<E>>async(
|
return Executioner.INSTANCE.<Optional<E>>async(sessionOps, uow, extractor, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
|
|
||||||
protected final AbstractSessionOperations sessionOps;
|
protected final AbstractSessionOperations sessionOps;
|
||||||
|
|
||||||
public abstract Statement buildStatement();
|
public abstract Statement buildStatement(boolean cached);
|
||||||
|
|
||||||
protected boolean showValues = true;
|
protected boolean showValues = true;
|
||||||
protected TraceContext traceContext;
|
protected TraceContext traceContext;
|
||||||
|
@ -181,7 +181,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Statement options(Statement statement) {
|
public Statement options(Statement statement) {
|
||||||
|
|
||||||
if (defaultTimestamp != null) {
|
if (defaultTimestamp != null) {
|
||||||
statement.setDefaultTimestamp(defaultTimestamp[0]);
|
statement.setDefaultTimestamp(defaultTimestamp[0]);
|
||||||
|
@ -224,11 +224,11 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement statement() {
|
public Statement statement() {
|
||||||
return buildStatement();
|
return buildStatement(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String cql() {
|
public String cql() {
|
||||||
Statement statement = buildStatement();
|
Statement statement = buildStatement(false);
|
||||||
if (statement == null) return "";
|
if (statement == null) return "";
|
||||||
if (statement instanceof BuiltStatement) {
|
if (statement instanceof BuiltStatement) {
|
||||||
BuiltStatement buildStatement = (BuiltStatement) statement;
|
BuiltStatement buildStatement = (BuiltStatement) statement;
|
||||||
|
@ -240,7 +240,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
|
|
||||||
public PreparedStatement prepareStatement() {
|
public PreparedStatement prepareStatement() {
|
||||||
|
|
||||||
Statement statement = buildStatement();
|
Statement statement = buildStatement(true);
|
||||||
|
|
||||||
if (statement instanceof RegularStatement) {
|
if (statement instanceof RegularStatement) {
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
|
|
||||||
public ListenableFuture<PreparedStatement> prepareStatementAsync() {
|
public ListenableFuture<PreparedStatement> prepareStatementAsync() {
|
||||||
|
|
||||||
Statement statement = buildStatement();
|
Statement statement = buildStatement(true);
|
||||||
|
|
||||||
if (statement instanceof RegularStatement) {
|
if (statement instanceof RegularStatement) {
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
|
|
||||||
public abstract Stream<E> transform(ResultSet resultSet);
|
public abstract Stream<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
protected AbstractCache getCache() {
|
public AbstractCache getCache() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,22 +59,18 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<E> sync() {
|
public Stream<E> sync() {
|
||||||
return Executioner.INSTANCE.<Stream<E>>sync(
|
return Executioner.INSTANCE.<Stream<E>>sync(sessionOps, null, traceContext, this, showValues);
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<E> sync(UnitOfWork uow) {
|
public Stream<E> sync(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<Stream<E>>sync(
|
return Executioner.INSTANCE.<Stream<E>>sync(sessionOps, uow, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Stream<E>> async() {
|
public CompletableFuture<Stream<E>> async() {
|
||||||
return Executioner.INSTANCE.<Stream<E>>async(
|
return Executioner.INSTANCE.<Stream<E>>async(sessionOps, null, traceContext, this, showValues);
|
||||||
sessionOps, null, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Stream<E>> async(UnitOfWork uow) {
|
public CompletableFuture<Stream<E>> async(UnitOfWork uow) {
|
||||||
return Executioner.INSTANCE.<Stream<E>>async(
|
return Executioner.INSTANCE.<Stream<E>>async(sessionOps, uow, traceContext, this, showValues);
|
||||||
sessionOps, uow, options(buildStatement()), getCache(), traceContext, this, showValues);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public final class BoundOperation<E> extends AbstractOperation<E, BoundOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement() {
|
public Statement buildStatement(boolean cached) {
|
||||||
return boundStatement;
|
return boundStatement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public final class BoundOptionalOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCache getCache() {
|
public AbstractCache getCache() {
|
||||||
return delegate.getCache();
|
return delegate.getCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public final class BoundOptionalOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement() {
|
public Statement buildStatement(boolean cached) {
|
||||||
return boundStatement;
|
return boundStatement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public final class BoundStreamOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCache getCache() {
|
public AbstractCache getCache() {
|
||||||
return delegate.getCache();
|
return delegate.getCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public final class BoundStreamOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement() {
|
public Statement buildStatement(boolean cached) {
|
||||||
return boundStatement;
|
return boundStatement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.Statement;
|
import com.datastax.driver.core.Statement;
|
||||||
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class CacheKey implements Serializable {
|
public class CacheKey implements Serializable {
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
private HelenusEntity entity;
|
||||||
static String of(Statement statement) {
|
|
||||||
return "use " + statement.getKeyspace() + "; " + statement.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheKey() {}
|
CacheKey() {}
|
||||||
|
|
||||||
CacheKey(String key) {
|
CacheKey(HelenusEntity entity, String key) {
|
||||||
|
this.entity = entity;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +22,7 @@ public class CacheKey implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return key;
|
return entity.getName() + "." + key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -40,7 +40,7 @@ public final class CountOperation extends AbstractFilterOperation<Long, CountOpe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
filters.forEach(f -> addPropertyNode(f.getNode()));
|
filters.forEach(f -> addPropertyNode(f.getNode()));
|
||||||
|
|
|
@ -46,7 +46,7 @@ public final class DeleteOperation extends AbstractFilterOperation<ResultSet, De
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
filters.forEach(f -> addPropertyNode(f.getNode()));
|
filters.forEach(f -> addPropertyNode(f.getNode()));
|
||||||
|
|
|
@ -6,79 +6,93 @@ import brave.propagation.TraceContext;
|
||||||
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 java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
|
|
||||||
|
|
||||||
public enum Executioner {
|
public enum Executioner {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
<E> E sync(
|
<E> E sync(AbstractSessionOperations session, UnitOfWork uow, Function<E, ?> extractor,
|
||||||
AbstractSessionOperations session,
|
TraceContext traceContext, OperationsDelegate<E> delegate, boolean showValues) {
|
||||||
UnitOfWork uow,
|
return this.<E>execute(session, uow, traceContext, delegate, showValues);
|
||||||
Statement statement,
|
|
||||||
AbstractCache cache,
|
|
||||||
TraceContext traceContext,
|
|
||||||
OperationsDelegate<E> delegate,
|
|
||||||
boolean showValues) {
|
|
||||||
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
|
||||||
return this.<E>execute(
|
|
||||||
futureResultSet, session, uow, statement, cache, traceContext, delegate, showValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E> CompletableFuture<E> async(
|
public <E> CompletableFuture<E> async(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext,
|
||||||
AbstractSessionOperations session,
|
OperationsDelegate<E> delegate, boolean showValues) {
|
||||||
UnitOfWork uow,
|
return CompletableFuture.<E>supplyAsync(() -> execute(session, uow, traceContext, delegate, showValues));
|
||||||
Statement statement,
|
|
||||||
AbstractCache cache,
|
|
||||||
TraceContext traceContext,
|
|
||||||
OperationsDelegate<E> delegate,
|
|
||||||
boolean showValues) {
|
|
||||||
|
|
||||||
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
|
||||||
return CompletableFuture.<E>supplyAsync(
|
|
||||||
() ->
|
|
||||||
execute(
|
|
||||||
futureResultSet, session, uow, statement, cache, traceContext, delegate, showValues));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E> E execute(
|
public <E> E execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext,
|
||||||
ResultSetFuture futureResultSet,
|
OperationsDelegate<E> delegate, boolean showValues) {
|
||||||
AbstractSessionOperations session,
|
|
||||||
UnitOfWork uow,
|
|
||||||
Statement statement,
|
|
||||||
AbstractCache cache,
|
|
||||||
TraceContext traceContext,
|
|
||||||
OperationsDelegate<E> delegate,
|
|
||||||
boolean showValues) {
|
|
||||||
|
|
||||||
|
// Start recording in a Zipkin sub-span our execution time to perform this operation.
|
||||||
Tracer tracer = session.getZipkinTracer();
|
Tracer tracer = session.getZipkinTracer();
|
||||||
Span span = null;
|
Span span = null;
|
||||||
if (tracer != null && traceContext != null) {
|
if (tracer != null && traceContext != null) {
|
||||||
span = tracer.newChild(traceContext);
|
span = tracer.newChild(traceContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uow != null) {
|
|
||||||
cache = uow.getCacheEnclosing(cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (span != null) {
|
if (span != null) {
|
||||||
span.name("cassandra");
|
span.name("cassandra");
|
||||||
span.start();
|
span.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultSet resultSet;
|
// Determine if we are caching and if so where to put the results.
|
||||||
if (cache != null) {
|
AbstractCache<CacheKey, Object> cache = null;
|
||||||
resultSet = cache.apply(statement, delegate, futureResultSet);
|
boolean prepareStatementForCaching = false;
|
||||||
|
if (uow != null ) {
|
||||||
|
prepareStatementForCaching = true;
|
||||||
|
cache = uow.getCacheEnclosing(delegate.getCache());
|
||||||
} else {
|
} else {
|
||||||
resultSet = futureResultSet.get();
|
cache = delegate.getCache();
|
||||||
|
prepareStatementForCaching = cache != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
E result = delegate.transform(resultSet);
|
// TODO: first, ask the delegate for the cacheKey
|
||||||
|
// if this is a SELECT query:
|
||||||
|
// if not in cache build the statement, execute the future, cache the result, transform the result then cache the transformations
|
||||||
|
// if INSERT/UPSERT/UPDATE
|
||||||
|
// if DELETE
|
||||||
|
// if COUNT
|
||||||
|
CacheKey key = (cache == null) ? null : delegate.getCacheKey();
|
||||||
|
E result = null;
|
||||||
|
|
||||||
|
if (key != null && cache != null) {
|
||||||
|
// Right now we only support Optional<Entity> fetch via complete primary key.
|
||||||
|
Object value = cache.get(key);
|
||||||
|
if (value != null) {
|
||||||
|
result = (E) Optional.of(value);
|
||||||
|
// if log statements: log cache hit for entity, primary key
|
||||||
|
// metrics.cacheHit +1
|
||||||
|
} else {
|
||||||
|
// if log statements: log cache miss for entity, primary key
|
||||||
|
// metrics.cacheMiss +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
if (result == null) {
|
||||||
|
Statement statement = delegate.options(delegate.buildStatement(prepareStatementForCaching));
|
||||||
|
// if log statements... log it here.
|
||||||
|
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
||||||
|
resultSet = futureResultSet.get();
|
||||||
|
}
|
||||||
|
result = delegate.transform(resultSet);
|
||||||
|
|
||||||
|
if (cache != null) {
|
||||||
|
updateCache.apply(result, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (E) result;
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -87,4 +101,5 @@ public enum Executioner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
||||||
values.forEach(t -> addPropertyNode(t._1));
|
values.forEach(t -> addPropertyNode(t._1));
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.Statement;
|
||||||
|
|
||||||
|
|
||||||
|
interface OperationsDelegate<E> {
|
||||||
|
|
||||||
|
Statement buildStatement(boolean cached);
|
||||||
|
|
||||||
|
Statement options(Statement statement);
|
||||||
|
|
||||||
public interface OperationsDelegate<E> {
|
|
||||||
E transform(ResultSet resultSet);
|
E transform(ResultSet resultSet);
|
||||||
|
|
||||||
|
AbstractCache getCache();
|
||||||
|
|
||||||
CacheKey getCacheKey();
|
CacheKey getCacheKey();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public final class PreparedStreamOperation<E> {
|
||||||
key = key.replaceFirst(Pattern.quote("?"), param.toString());
|
key = key.replaceFirst(Pattern.quote("?"), param.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundStreamOperation<E>(boundStatement, new CacheKey(key), operation);
|
return new BoundStreamOperation<E>(boundStatement, operation.getCacheKey(), operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,8 +38,18 @@ public final class SelectFirstOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public AbstractCache getCache() {
|
||||||
return src.buildStatement();
|
return src.getCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CacheKey getCacheKey() {
|
||||||
|
return src.getCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
return src.buildStatement(cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,8 +36,8 @@ public final class SelectFirstTransformingOperation<R, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
return src.buildStatement();
|
return src.buildStatement(cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,6 +27,9 @@ import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
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.*;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
@ -166,13 +169,6 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractCache getCache() {
|
|
||||||
if (!ignoreSessionCache) {
|
|
||||||
return sessionOps.getSessionCache();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<E> ignoreCache() {
|
public SelectOperation<E> ignoreCache() {
|
||||||
ignoreSessionCache = true;
|
ignoreSessionCache = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -189,17 +185,53 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public AbstractCache getCache() {// TODO, not really public API...
|
||||||
|
if (!ignoreSessionCache) {
|
||||||
|
return sessionOps.getSessionCache();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CacheKey getCacheKey() {
|
||||||
|
|
||||||
|
List<String>keys = new ArrayList<>(filters.size());
|
||||||
|
HelenusEntity entity = props.get(0).getEntity();
|
||||||
|
|
||||||
|
for (HelenusPropertyNode prop : props) {
|
||||||
|
switch(prop.getProperty().getColumnType()) {
|
||||||
|
case PARTITION_KEY:
|
||||||
|
case CLUSTERING_COLUMN:
|
||||||
|
|
||||||
|
Filter filter = filters.get(prop.getProperty());
|
||||||
|
if (filter != null) {
|
||||||
|
keys.add(filter.toString());
|
||||||
|
} else {
|
||||||
|
// we're missing a part of the primary key, so we can't create a proper cache key
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// We've past the primary key components in this ordered list, so we're done building
|
||||||
|
// the cache key.
|
||||||
|
if (keys.size() > 0) {
|
||||||
|
return new CacheKey(entity, Joiner.on(",").join(keys));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
||||||
HelenusEntity entity = null;
|
HelenusEntity entity = null;
|
||||||
Selection selection = QueryBuilder.select();
|
Selection selection = QueryBuilder.select();
|
||||||
|
|
||||||
// iff in txn or cacheable add ttl and timestamp to result set for each col selected
|
|
||||||
// construct set of primary keys (partition and col)
|
|
||||||
// construct cache key
|
|
||||||
|
|
||||||
for (HelenusPropertyNode prop : props) {
|
for (HelenusPropertyNode prop : props) {
|
||||||
selection = selection.column(prop.getColumnName());
|
String columnName = prop.getColumnName();
|
||||||
|
selection = selection.column(columnName);
|
||||||
|
|
||||||
if (prop.getProperty().caseSensitiveIndex()) {
|
if (prop.getProperty().caseSensitiveIndex()) {
|
||||||
allowFiltering = true;
|
allowFiltering = true;
|
||||||
|
@ -214,6 +246,25 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
+ " or "
|
+ " or "
|
||||||
+ prop.getEntity().getMappingInterface());
|
+ prop.getEntity().getMappingInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cached) {
|
||||||
|
switch(prop.getProperty().getColumnType()) {
|
||||||
|
case PARTITION_KEY:
|
||||||
|
case CLUSTERING_COLUMN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (entity.equals(prop.getEntity())) {
|
||||||
|
if (prop.getNext().isPresent()) {
|
||||||
|
columnName = Iterables.getLast(prop).getColumnName().toCql(true);
|
||||||
|
}
|
||||||
|
if (!prop.getProperty().getDataType().isCollectionType()) {
|
||||||
|
selection.writeTime(columnName);
|
||||||
|
selection.ttl(columnName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
@ -234,7 +285,7 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
|
|
||||||
Where where = select.where();
|
Where where = select.where();
|
||||||
|
|
||||||
for (Filter<?> filter : filters) {
|
for (Filter<?> filter : filters.values()) {
|
||||||
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,12 @@ public final class SelectTransformingOperation<R, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
return src.buildStatement();
|
return src.buildStatement(cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCache getCache() {
|
public AbstractCache getCache() {
|
||||||
return src.getCache();
|
return src.getCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,31 +6,20 @@ import com.datastax.driver.core.Statement;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class SessionCache extends AbstractCache<String, ResultSet> {
|
public class SessionCache extends AbstractCache<CacheKey, ResultSet> {
|
||||||
|
|
||||||
protected ResultSet apply(
|
protected ResultSet apply(CacheKey key, OperationsDelegate delegate)
|
||||||
Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
final CacheKey key = delegate.getCacheKey();
|
|
||||||
final String cacheKey = (key == null) ? CacheKey.of(statement) : key.toString();
|
|
||||||
ResultSet resultSet = null;
|
ResultSet resultSet = null;
|
||||||
if (cacheKey == null) {
|
resultSet = cache.getIfPresent(key);
|
||||||
resultSet = resultSetFuture.get();
|
|
||||||
} else {
|
|
||||||
resultSet = cache.getIfPresent(cacheKey);
|
|
||||||
if (resultSet == null) {
|
|
||||||
resultSet = resultSetFuture.get();
|
|
||||||
if (resultSet != null) {
|
if (resultSet != null) {
|
||||||
cache.put(cacheKey, resultSet);
|
cache.put(key, resultSet);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSet get(Statement statement, OperationsDelegate delegate) {
|
|
||||||
final CacheKey key = delegate.getCacheKey();
|
|
||||||
final String cacheKey = (key == null) ? CacheKey.of(statement) : key.toString();
|
|
||||||
return cache.getIfPresent(cacheKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import java.util.Optional;
|
||||||
import com.datastax.driver.core.ResultSetFuture;
|
|
||||||
import com.datastax.driver.core.Statement;
|
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
|
|
||||||
import java.util.HashMap;
|
public class UnitOfWorkCache extends AbstractCache<CacheKey, Object> {
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class UnitOfWorkCache extends AbstractCache<String, ResultSet> {
|
|
||||||
|
|
||||||
private final UnitOfWork uow;
|
private final UnitOfWork uow;
|
||||||
private final Map<String, ResultSet> cache = new HashMap<String, ResultSet>();
|
private AbstractCache<CacheKey, Object> sessionCache;
|
||||||
private AbstractCache sessionCache;
|
|
||||||
|
|
||||||
public UnitOfWorkCache(UnitOfWork uow, AbstractCache sessionCache) {
|
public UnitOfWorkCache(UnitOfWork uow, AbstractCache sessionCache) {
|
||||||
super();
|
super();
|
||||||
|
@ -22,32 +16,22 @@ public class UnitOfWorkCache extends AbstractCache<String, ResultSet> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResultSet apply(Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
Object get(CacheKey key) {
|
||||||
throws InterruptedException, ExecutionException {
|
Object result = null;
|
||||||
return resultSetFuture.get();
|
UnitOfWork parent = null;
|
||||||
/*
|
do {
|
||||||
final CacheKey key = delegate.getCacheKey();
|
result = uow.getCache().get(key);
|
||||||
final String cacheKey = (key == null) ? CacheKey.of(statement) : key.toString();
|
parent = uow.getEnclosingUnitOfWork();
|
||||||
ResultSet resultSet = null;
|
} while(result == null && parent != null);
|
||||||
if (cacheKey == null) {
|
if (result == null) {
|
||||||
if (sessionCache != null) {
|
result = sessionCache.get(key);
|
||||||
ResultSet rs = sessionCache.apply(statement, delegate, resultSetFuture);
|
|
||||||
if (rs != null) {
|
|
||||||
return rs;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
resultSet = cache.get(cacheKey);
|
@Override
|
||||||
if (resultSet != null) {
|
void put(CacheKey key, Object result) {
|
||||||
return resultSet;
|
cache.put(key, result);
|
||||||
}
|
|
||||||
}
|
|
||||||
resultSet = resultSetFuture.get();
|
|
||||||
if (resultSet != null) {
|
|
||||||
cache.put(cacheKey, resultSet);
|
|
||||||
}
|
|
||||||
return resultSet;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -507,7 +507,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new HelenusMappingException("empty update operation");
|
throw new HelenusMappingException("empty update operation");
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package net.helenus.mapping.javatype;
|
||||||
|
|
||||||
|
public abstract class AbstractCollectionJavaType extends AbstractJavaType {
|
||||||
|
|
||||||
|
public static boolean isCollectionType() { return true; }
|
||||||
|
|
||||||
|
}
|
|
@ -33,6 +33,8 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public abstract class AbstractJavaType {
|
public abstract class AbstractJavaType {
|
||||||
|
|
||||||
|
public static boolean isCollectionType() { return false; }
|
||||||
|
|
||||||
public abstract Class<?> getJavaClass();
|
public abstract Class<?> getJavaClass();
|
||||||
|
|
||||||
public boolean isApplicable(Class<?> javaClass) {
|
public boolean isApplicable(Class<?> javaClass) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ import net.helenus.mapping.type.UDTListDataType;
|
||||||
import net.helenus.support.Either;
|
import net.helenus.support.Either;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class ListJavaType extends AbstractJavaType {
|
public final class ListJavaType extends AbstractCollectionJavaType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getJavaClass() {
|
public Class<?> getJavaClass() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package net.helenus.mapping.javatype;
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.AbstractCollection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -31,7 +32,7 @@ import net.helenus.mapping.type.*;
|
||||||
import net.helenus.support.Either;
|
import net.helenus.support.Either;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class MapJavaType extends AbstractJavaType {
|
public final class MapJavaType extends AbstractCollectionJavaType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getJavaClass() {
|
public Class<?> getJavaClass() {
|
||||||
|
|
|
@ -35,7 +35,7 @@ import net.helenus.mapping.type.UDTSetDataType;
|
||||||
import net.helenus.support.Either;
|
import net.helenus.support.Either;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class SetJavaType extends AbstractJavaType {
|
public final class SetJavaType extends AbstractCollectionJavaType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getJavaClass() {
|
public Class<?> getJavaClass() {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package net.helenus.mapping.type;
|
||||||
|
|
||||||
|
import net.helenus.mapping.ColumnType;
|
||||||
|
|
||||||
|
public abstract class AbstractCollectionDataType extends AbstractDataType {
|
||||||
|
|
||||||
|
public AbstractCollectionDataType(ColumnType columnType) {
|
||||||
|
super(columnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCollectionType() { return true; }
|
||||||
|
|
||||||
|
}
|
|
@ -54,4 +54,7 @@ public abstract class AbstractDataType {
|
||||||
throw new HelenusMappingException(
|
throw new HelenusMappingException(
|
||||||
"wrong column type " + columnType + " for UserDefinedType in columnName " + columnName);
|
"wrong column type " + columnType + " for UserDefinedType in columnName " + columnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCollectionType() { return false; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public final class DTDataType extends AbstractDataType {
|
||||||
private final DataType dataType;
|
private final DataType dataType;
|
||||||
private final Class<?> javaClass;
|
private final Class<?> javaClass;
|
||||||
private final Class<?>[] typeArguments;
|
private final Class<?>[] typeArguments;
|
||||||
|
private final boolean isCollectionType;
|
||||||
|
|
||||||
public DTDataType(ColumnType columnType, DataType dataType) {
|
public DTDataType(ColumnType columnType, DataType dataType) {
|
||||||
this(
|
this(
|
||||||
|
@ -53,6 +54,7 @@ public final class DTDataType extends AbstractDataType {
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.javaClass = javaClass;
|
this.javaClass = javaClass;
|
||||||
this.typeArguments = typeArguments;
|
this.typeArguments = typeArguments;
|
||||||
|
this.isCollectionType = dataType.isCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DTDataType list(
|
public static DTDataType list(
|
||||||
|
@ -193,6 +195,10 @@ public final class DTDataType extends AbstractDataType {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCollectionType() {
|
||||||
|
return isCollectionType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return dataType.toString();
|
return dataType.toString();
|
||||||
|
|
|
@ -18,12 +18,14 @@ package net.helenus.mapping.type;
|
||||||
import com.datastax.driver.core.DataType;
|
import com.datastax.driver.core.DataType;
|
||||||
import com.datastax.driver.core.UserType;
|
import com.datastax.driver.core.UserType;
|
||||||
import com.datastax.driver.core.schemabuilder.*;
|
import com.datastax.driver.core.schemabuilder.*;
|
||||||
|
|
||||||
|
import java.util.AbstractCollection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.helenus.mapping.ColumnType;
|
import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.IdentityName;
|
import net.helenus.mapping.IdentityName;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class UDTKeyMapDataType extends AbstractDataType {
|
public final class UDTKeyMapDataType extends AbstractCollectionDataType {
|
||||||
|
|
||||||
private final IdentityName keyType;
|
private final IdentityName keyType;
|
||||||
private final Class<?> udtKeyClass;
|
private final Class<?> udtKeyClass;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.IdentityName;
|
import net.helenus.mapping.IdentityName;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class UDTListDataType extends AbstractDataType {
|
public final class UDTListDataType extends AbstractCollectionDataType {
|
||||||
|
|
||||||
private final IdentityName udtName;
|
private final IdentityName udtName;
|
||||||
private final Class<?> udtClass;
|
private final Class<?> udtClass;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.IdentityName;
|
import net.helenus.mapping.IdentityName;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class UDTMapDataType extends AbstractDataType {
|
public final class UDTMapDataType extends AbstractCollectionDataType {
|
||||||
|
|
||||||
private final IdentityName keyType;
|
private final IdentityName keyType;
|
||||||
private final Class<?> udtKeyClass;
|
private final Class<?> udtKeyClass;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.IdentityName;
|
import net.helenus.mapping.IdentityName;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class UDTSetDataType extends AbstractDataType {
|
public final class UDTSetDataType extends AbstractCollectionDataType {
|
||||||
|
|
||||||
private final IdentityName udtName;
|
private final IdentityName udtName;
|
||||||
private final Class<?> udtClass;
|
private final Class<?> udtClass;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.IdentityName;
|
import net.helenus.mapping.IdentityName;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class UDTValueMapDataType extends AbstractDataType {
|
public final class UDTValueMapDataType extends AbstractCollectionDataType {
|
||||||
|
|
||||||
private final DataType keyType;
|
private final DataType keyType;
|
||||||
private final IdentityName valueType;
|
private final IdentityName valueType;
|
||||||
|
|
|
@ -17,9 +17,11 @@ 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 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.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.support.Fun;
|
import net.helenus.support.Fun;
|
||||||
|
@ -248,6 +250,25 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
Assert.assertEquals(0L, cnt);
|
Assert.assertEquals(0L, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testZipkin() throws Exception {
|
||||||
|
session
|
||||||
|
.update()
|
||||||
|
.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();
|
||||||
|
update
|
||||||
|
.set(user::name, null)
|
||||||
|
.zipkinContext(null)
|
||||||
|
.sync();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void assertUsers(User expected, User actual) {
|
private void assertUsers(User expected, User actual) {
|
||||||
Assert.assertEquals(expected.id(), actual.id());
|
Assert.assertEquals(expected.id(), actual.id());
|
||||||
Assert.assertEquals(expected.name(), actual.name());
|
Assert.assertEquals(expected.name(), actual.name());
|
||||||
|
|
|
@ -62,14 +62,13 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
|
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
|
||||||
/*
|
|
||||||
Widget w1, w2, w3, w4;
|
Widget w1, w2, w3, w4;
|
||||||
UUID key = UUIDs.timeBased();
|
UUID key = UUIDs.timeBased();
|
||||||
|
|
||||||
try (UnitOfWork uow = session.begin()) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
|
||||||
// This should cache the inserted Widget.
|
// This should cache the inserted Widget.
|
||||||
w1 = session.<Widget>upsert(widget)
|
w1 = session.<Widget>insert(widget)
|
||||||
.value(widget::id, key)
|
.value(widget::id, key)
|
||||||
.value(widget::name, RandomString.make(20))
|
.value(widget::name, RandomString.make(20))
|
||||||
.sync(uow);
|
.sync(uow);
|
||||||
|
@ -106,7 +105,6 @@ public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
Assert.assertNotEquals(w1, w4);
|
Assert.assertNotEquals(w1, w4);
|
||||||
Assert.assertTrue(w1.equals(w4));
|
Assert.assertTrue(w1.equals(w4));
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue