Formatting
This commit is contained in:
parent
306c9e68ef
commit
74832a32dd
56 changed files with 1133 additions and 1095 deletions
|
@ -35,7 +35,7 @@ public enum GetterMethodDetector implements Function<Method, Boolean> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Modifier.isStatic(method.getModifiers())) {
|
if (Modifier.isStatic(method.getModifiers())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods marked "Transient" are not mapped, skip them.
|
// Methods marked "Transient" are not mapped, skip them.
|
||||||
|
|
|
@ -1,41 +1,38 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import net.helenus.core.reflect.MapExportable;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import net.helenus.core.reflect.MapExportable;
|
||||||
|
|
||||||
public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<E> {
|
public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<E> {
|
||||||
|
|
||||||
public AbstractAuditedEntityDraft(MapExportable entity) {
|
public AbstractAuditedEntityDraft(MapExportable entity) {
|
||||||
super(entity);
|
super(entity);
|
||||||
|
|
||||||
Date in = new Date();
|
Date in = new Date();
|
||||||
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
|
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
|
||||||
Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
|
Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
|
||||||
String who = getCurrentAuditor();
|
String who = getCurrentAuditor();
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
if (who != null) {
|
if (who != null) {
|
||||||
set("createdBy", who);
|
set("createdBy", who);
|
||||||
}
|
}
|
||||||
set("createdAt", now);
|
set("createdAt", now);
|
||||||
}
|
|
||||||
if (who != null) {
|
|
||||||
set("modifiedBy", who);
|
|
||||||
}
|
|
||||||
set("modifiedAt", now);
|
|
||||||
}
|
}
|
||||||
|
if (who != null) {
|
||||||
protected String getCurrentAuditor() {
|
set("modifiedBy", who);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
set("modifiedAt", now);
|
||||||
|
}
|
||||||
|
|
||||||
public Date createdAt() {
|
protected String getCurrentAuditor() {
|
||||||
return (Date) get("createdAt", Date.class);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date createdAt() {
|
||||||
|
return (Date) get("createdAt", Date.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,164 +1,159 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.google.common.primitives.Primitives;
|
import com.google.common.primitives.Primitives;
|
||||||
|
import java.util.*;
|
||||||
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
||||||
import net.helenus.core.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
|
|
||||||
|
|
||||||
public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
public abstract class AbstractEntityDraft<E> implements Drafted<E> {
|
||||||
|
|
||||||
private final Map<String, Object> backingMap = new HashMap<String, Object>();
|
private final Map<String, Object> backingMap = new HashMap<String, Object>();
|
||||||
private final MapExportable entity;
|
private final MapExportable entity;
|
||||||
private final Map<String, Object> entityMap;
|
private final Map<String, Object> entityMap;
|
||||||
|
|
||||||
|
public AbstractEntityDraft(MapExportable entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.entityMap = entity != null ? entity.toMap() : new HashMap<String, Object>();
|
||||||
|
}
|
||||||
|
|
||||||
public AbstractEntityDraft(MapExportable entity) {
|
public abstract Class<E> getEntityClass();
|
||||||
this.entity = entity;
|
|
||||||
this.entityMap = entity != null ? entity.toMap() : new HashMap<String, Object>();
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
||||||
|
return (T) get(this.<T>methodNameFor(getter), returnType);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T get(Getter<T> getter, Class<?> returnType) {
|
protected <T> T get(String key, Class<?> returnType) {
|
||||||
return (T) get(this.<T>methodNameFor(getter), returnType);
|
T value = (T) backingMap.get(key);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
if (value == null) {
|
||||||
protected <T> T get(String key, Class<?> returnType) {
|
value = (T) entityMap.get(key);
|
||||||
T value = (T) backingMap.get(key);
|
if (value == null) {
|
||||||
|
|
||||||
if (value == null) {
|
if (Primitives.allPrimitiveTypes().contains(returnType)) {
|
||||||
value = (T) entityMap.get(key);
|
|
||||||
if (value == null) {
|
|
||||||
|
|
||||||
if (Primitives.allPrimitiveTypes().contains(returnType)) {
|
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
|
||||||
|
if (type == null) {
|
||||||
|
throw new RuntimeException("unknown primitive type " + returnType);
|
||||||
|
}
|
||||||
|
|
||||||
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
|
return (T) type.getDefaultValue();
|
||||||
if (type == null) {
|
|
||||||
throw new RuntimeException("unknown primitive type " + returnType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (T) type.getDefaultValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Object set(Getter<T> getter, Object value) {
|
return value;
|
||||||
return set(this.<T>methodNameFor(getter), value);
|
}
|
||||||
|
|
||||||
|
protected <T> Object set(Getter<T> getter, Object value) {
|
||||||
|
return set(this.<T>methodNameFor(getter), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object set(String key, Object value) {
|
||||||
|
if (key == null || value == null) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object set(String key, Object value) {
|
backingMap.put(key, value);
|
||||||
if (key == null || value == null) {
|
return value;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T> T mutate(Getter<T> getter, T value) {
|
||||||
|
return (T) mutate(this.<T>methodNameFor(getter), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object mutate(String key, Object value) {
|
||||||
|
Objects.requireNonNull(key);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
|
Map<String, Object> map = entity.toMap();
|
||||||
|
|
||||||
|
if (map.containsKey(key) && !value.equals(map.get(key))) {
|
||||||
backingMap.put(key, value);
|
backingMap.put(key, value);
|
||||||
return value;
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map.get(key);
|
||||||
|
} else {
|
||||||
|
backingMap.put(key, value);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private <T> String methodNameFor(Getter<T> getter) {
|
||||||
protected <T> T mutate(Getter<T> getter, T value) {
|
return MappingUtil.resolveMappingProperty(getter).getProperty().getPropertyName();
|
||||||
return (T) mutate(this.<T>methodNameFor(getter), value);
|
}
|
||||||
|
|
||||||
|
public <T> Object unset(Getter<T> getter) {
|
||||||
|
return unset(methodNameFor(getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unset(String key) {
|
||||||
|
if (key != null) {
|
||||||
|
Object value = backingMap.get(key);
|
||||||
|
backingMap.put(key, null);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected Object mutate(String key, Object value) {
|
public <T> boolean reset(Getter<T> getter, T desiredValue) {
|
||||||
Objects.requireNonNull(key);
|
return this.<T>reset(this.<T>methodNameFor(getter), desiredValue);
|
||||||
|
}
|
||||||
|
|
||||||
if (value == null) {
|
public <T> boolean reset(String key, T desiredValue) {
|
||||||
return null;
|
if (key != null && desiredValue != null) {
|
||||||
}
|
@SuppressWarnings("unchecked")
|
||||||
|
T currentValue = (T) backingMap.get(key);
|
||||||
if (entity != null) {
|
if (currentValue == null || !currentValue.equals(desiredValue)) {
|
||||||
Map<String, Object> map = entity.toMap();
|
set(key, desiredValue);
|
||||||
|
return true;
|
||||||
if (map.containsKey(key) && !value.equals(map.get(key))) {
|
}
|
||||||
backingMap.put(key, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return map.get(key);
|
|
||||||
} else {
|
|
||||||
backingMap.put(key, value);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private <T> String methodNameFor(Getter<T> getter) {
|
@Override
|
||||||
return MappingUtil.resolveMappingProperty(getter)
|
public Map<String, Object> toMap() {
|
||||||
.getProperty()
|
return toMap(entityMap);
|
||||||
.getPropertyName();
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> toMap(Map<String, Object> entityMap) {
|
||||||
|
Map<String, Object> combined;
|
||||||
|
if (entityMap != null && entityMap.size() > 0) {
|
||||||
|
combined = new HashMap<String, Object>(entityMap.size());
|
||||||
|
for (String key : entityMap.keySet()) {
|
||||||
|
combined.put(key, entityMap.get(key));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
combined = new HashMap<String, Object>(backingMap.size());
|
||||||
}
|
}
|
||||||
|
for (String key : mutated()) {
|
||||||
public <T> Object unset(Getter<T> getter) {
|
combined.put(key, backingMap.get(key));
|
||||||
return unset(methodNameFor(getter));
|
|
||||||
}
|
}
|
||||||
|
return combined;
|
||||||
|
}
|
||||||
|
|
||||||
public Object unset(String key) {
|
@Override
|
||||||
if (key != null) {
|
public Set<String> mutated() {
|
||||||
Object value = backingMap.get(key);
|
return backingMap.keySet();
|
||||||
backingMap.put(key, null);
|
}
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> boolean reset(Getter<T> getter, T desiredValue) {
|
|
||||||
return this.<T>reset(this.<T>methodNameFor(getter), desiredValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> boolean reset(String key, T desiredValue) {
|
|
||||||
if (key != null && desiredValue != null) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T currentValue = (T) backingMap.get(key);
|
|
||||||
if (currentValue == null || !currentValue.equals(desiredValue)) {
|
|
||||||
set(key, desiredValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> toMap() {
|
|
||||||
return toMap(entityMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> toMap(Map<String, Object>entityMap) {
|
|
||||||
Map<String, Object> combined;
|
|
||||||
if (entityMap != null && entityMap.size() > 0) {
|
|
||||||
combined = new HashMap<String, Object>(entityMap.size());
|
|
||||||
for (String key : entityMap.keySet()) {
|
|
||||||
combined.put(key, entityMap.get(key));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
combined = new HashMap<String, Object>(backingMap.size());
|
|
||||||
}
|
|
||||||
for (String key : mutated()) {
|
|
||||||
combined.put(key, backingMap.get(key));
|
|
||||||
}
|
|
||||||
return combined;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> mutated() {
|
|
||||||
return backingMap.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return backingMap.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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 com.google.common.util.concurrent.ListenableFuture;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||||
import net.helenus.mapping.value.ColumnValueProvider;
|
import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
@ -124,5 +123,4 @@ public abstract class AbstractSessionOperations {
|
||||||
void printCql(String cql) {
|
void printCql(String cql) {
|
||||||
getPrintStream().println(cql);
|
getPrintStream().println(cql);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,8 @@ package net.helenus.core;
|
||||||
|
|
||||||
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 java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
||||||
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork, AutoCloseable {
|
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork, AutoCloseable {
|
||||||
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
|
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
|
||||||
|
@ -70,22 +68,25 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Set<Object>> getCache() { return cache; }
|
public Map<String, Set<Object>> getCache() {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
private Iterator<AbstractUnitOfWork<E>> getChildNodes() {
|
private Iterator<AbstractUnitOfWork<E>> getChildNodes() {
|
||||||
return nested.iterator();
|
return nested.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if the work performed between calling begin and now can be committed or not.
|
* Checks to see if the work performed between calling begin and now can be committed or not.
|
||||||
*
|
*
|
||||||
* @return a function from which to chain work that only happens when commit is successful
|
* @return a function from which to chain work that only happens when commit is successful
|
||||||
* @throws E when the work overlaps with other concurrent writers.
|
* @throws E when the work overlaps with other concurrent writers.
|
||||||
*/
|
*/
|
||||||
public PostCommitFunction<Void, Void> commit() throws E {
|
public PostCommitFunction<Void, Void> commit() throws E {
|
||||||
// All nested UnitOfWork should be committed (not aborted) before calls to commit, check.
|
// All nested UnitOfWork should be committed (not aborted) before calls to commit, check.
|
||||||
boolean canCommit = true;
|
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)) {
|
for (AbstractUnitOfWork<E> uow : traverser.postOrderTraversal(this)) {
|
||||||
if (this != uow) {
|
if (this != uow) {
|
||||||
canCommit &= (!uow.aborted && uow.committed);
|
canCommit &= (!uow.aborted && uow.committed);
|
||||||
|
@ -112,7 +113,8 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
if (parentCache.containsKey(key)) {
|
if (parentCache.containsKey(key)) {
|
||||||
// merge the sets
|
// merge the sets
|
||||||
Set<Object> ps = parentCache.get(key);
|
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 {
|
} else {
|
||||||
// add the missing set
|
// add the missing set
|
||||||
parentCache.put(key, cache.get(key));
|
parentCache.put(key, cache.get(key));
|
||||||
|
@ -122,9 +124,12 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
|
|
||||||
// Apply all post-commit functions for
|
// Apply all post-commit functions for
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
traverser
|
||||||
uow.applyPostCommitFunctions();
|
.postOrderTraversal(this)
|
||||||
});
|
.forEach(
|
||||||
|
uow -> {
|
||||||
|
uow.applyPostCommitFunctions();
|
||||||
|
});
|
||||||
return new PostCommitFunction(this, null);
|
return new PostCommitFunction(this, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,11 +142,15 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
|
|
||||||
/* Explicitly discard the work and mark it as as such in the log. */
|
/* Explicitly discard the work and mark it as as such in the log. */
|
||||||
public void abort() {
|
public void abort() {
|
||||||
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes);
|
TreeTraverser<AbstractUnitOfWork<E>> traverser =
|
||||||
traverser.postOrderTraversal(this).forEach(uow -> {
|
TreeTraverser.using(node -> node::getChildNodes);
|
||||||
uow.committed = false;
|
traverser
|
||||||
uow.aborted = true;
|
.postOrderTraversal(this)
|
||||||
});
|
.forEach(
|
||||||
|
uow -> {
|
||||||
|
uow.committed = false;
|
||||||
|
uow.aborted = true;
|
||||||
|
});
|
||||||
// log.record(txn::abort)
|
// log.record(txn::abort)
|
||||||
// cache.invalidateSince(txn::start time)
|
// cache.invalidateSince(txn::start time)
|
||||||
}
|
}
|
||||||
|
@ -165,5 +174,4 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
|
||||||
public boolean hasCommitted() {
|
public boolean hasCommitted() {
|
||||||
return committed;
|
return committed;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface CommitThunk {
|
public interface CommitThunk {
|
||||||
void apply();
|
void apply();
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,10 +142,10 @@ public final class Helenus {
|
||||||
public static HelenusEntity entity(Class<?> iface) {
|
public static HelenusEntity entity(Class<?> iface) {
|
||||||
Metadata metadata = metadataForEntity.get(iface);
|
Metadata metadata = metadataForEntity.get(iface);
|
||||||
if (metadata == null) {
|
if (metadata == null) {
|
||||||
HelenusSession session = session();
|
HelenusSession session = session();
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
metadata = session.getMetadata();
|
metadata = session.getMetadata();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return entity(iface, metadata);
|
return entity(iface, metadata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,21 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import com.codahale.metrics.Meter;
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.datastax.driver.core.*;
|
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.operation.*;
|
||||||
import net.helenus.core.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
@ -33,19 +44,6 @@ import net.helenus.support.Fun.Tuple6;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
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 {
|
public final class HelenusSession extends AbstractSessionOperations implements Closeable {
|
||||||
|
|
||||||
private final int MAX_CACHE_SIZE = 10000;
|
private final int MAX_CACHE_SIZE = 10000;
|
||||||
|
@ -69,26 +67,25 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
private final StatementColumnValuePreparer valuePreparer;
|
private final StatementColumnValuePreparer valuePreparer;
|
||||||
private final Metadata metadata;
|
private final Metadata metadata;
|
||||||
|
|
||||||
|
|
||||||
HelenusSession(
|
HelenusSession(
|
||||||
Session session,
|
Session session,
|
||||||
String usingKeyspace,
|
String usingKeyspace,
|
||||||
CodecRegistry registry,
|
CodecRegistry registry,
|
||||||
boolean showCql,
|
boolean showCql,
|
||||||
PrintStream printStream,
|
PrintStream printStream,
|
||||||
SessionRepositoryBuilder sessionRepositoryBuilder,
|
SessionRepositoryBuilder sessionRepositoryBuilder,
|
||||||
Executor executor,
|
Executor executor,
|
||||||
boolean dropSchemaOnClose,
|
boolean dropSchemaOnClose,
|
||||||
ConsistencyLevel consistencyLevel,
|
ConsistencyLevel consistencyLevel,
|
||||||
boolean defaultQueryIdempotency,
|
boolean defaultQueryIdempotency,
|
||||||
Class<? extends UnitOfWork> unitOfWorkClass,
|
Class<? extends UnitOfWork> unitOfWorkClass,
|
||||||
MetricRegistry metricRegistry,
|
MetricRegistry metricRegistry,
|
||||||
Tracer tracer) {
|
Tracer tracer) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
||||||
this.usingKeyspace =
|
this.usingKeyspace =
|
||||||
Objects.requireNonNull(
|
Objects.requireNonNull(
|
||||||
usingKeyspace, "keyspace needs to be selected before creating session");
|
usingKeyspace, "keyspace needs to be selected before creating session");
|
||||||
this.showCql = showCql;
|
this.showCql = showCql;
|
||||||
this.printStream = printStream;
|
this.printStream = printStream;
|
||||||
this.sessionRepository = sessionRepositoryBuilder.build();
|
this.sessionRepository = sessionRepositoryBuilder.build();
|
||||||
|
@ -177,42 +174,53 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getDefaultQueryIdempotency() { return defaultQueryIdempotency; }
|
public boolean getDefaultQueryIdempotency() {
|
||||||
|
return defaultQueryIdempotency;
|
||||||
|
}
|
||||||
|
|
||||||
public Metadata getMetadata() { return metadata; }
|
public Metadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized <T extends UnitOfWork> T begin() {
|
public synchronized <T extends UnitOfWork> T begin() {
|
||||||
return begin(null);
|
return begin(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized <T extends UnitOfWork> T begin(T parent) {
|
public synchronized <T extends UnitOfWork> T begin(T parent) {
|
||||||
try {
|
try {
|
||||||
Class<? extends UnitOfWork> clazz = unitOfWorkClass;
|
Class<? extends UnitOfWork> clazz = unitOfWorkClass;
|
||||||
Constructor<? extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
|
Constructor<? extends UnitOfWork> ctor =
|
||||||
|
clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
|
||||||
UnitOfWork uow = ctor.newInstance(this, parent);
|
UnitOfWork uow = ctor.newInstance(this, parent);
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.addNestedUnitOfWork(uow);
|
parent.addNestedUnitOfWork(uow);
|
||||||
}
|
}
|
||||||
return (T) uow.begin();
|
return (T) uow.begin();
|
||||||
}
|
} catch (NoSuchMethodException
|
||||||
catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
| InvocationTargetException
|
||||||
throw new HelenusException(String.format("Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()), e);
|
| InstantiationException
|
||||||
|
| IllegalAccessException e) {
|
||||||
|
throw new HelenusException(
|
||||||
|
String.format(
|
||||||
|
"Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E> SelectOperation<E> select(E pojo) {
|
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();
|
ColumnValueProvider valueProvider = getValueProvider();
|
||||||
HelenusEntity entity = Helenus.resolve(pojo);
|
HelenusEntity entity = Helenus.resolve(pojo);
|
||||||
Class<?> entityClass = entity.getMappingInterface();
|
Class<?> entityClass = entity.getMappingInterface();
|
||||||
|
|
||||||
return new SelectOperation<E>(
|
return new SelectOperation<E>(
|
||||||
this,
|
this,
|
||||||
entity,
|
entity,
|
||||||
(r) -> {
|
(r) -> {
|
||||||
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
||||||
return (E) Helenus.map(entityClass, map);
|
return (E) Helenus.map(entityClass, map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E> SelectOperation<E> select(Class<E> entityClass) {
|
public <E> SelectOperation<E> select(Class<E> entityClass) {
|
||||||
|
@ -221,12 +229,12 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
HelenusEntity entity = Helenus.entity(entityClass);
|
HelenusEntity entity = Helenus.entity(entityClass);
|
||||||
|
|
||||||
return new SelectOperation<E>(
|
return new SelectOperation<E>(
|
||||||
this,
|
this,
|
||||||
entity,
|
entity,
|
||||||
(r) -> {
|
(r) -> {
|
||||||
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
||||||
return (E) Helenus.map(entityClass, map);
|
return (E) Helenus.map(entityClass, map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectOperation<Fun.ArrayTuple> select() {
|
public SelectOperation<Fun.ArrayTuple> select() {
|
||||||
|
@ -239,7 +247,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E> SelectOperation<Row> selectAll(E pojo) {
|
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);
|
HelenusEntity entity = Helenus.resolve(pojo);
|
||||||
return new SelectOperation<Row>(this, entity);
|
return new SelectOperation<Row>(this, entity);
|
||||||
}
|
}
|
||||||
|
@ -411,51 +420,62 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
|
|
||||||
public <E> UpdateOperation<E> update(Drafted<E> drafted) {
|
public <E> UpdateOperation<E> update(Drafted<E> drafted) {
|
||||||
if (drafted instanceof AbstractEntityDraft == false) {
|
if (drafted instanceof AbstractEntityDraft == false) {
|
||||||
throw new HelenusMappingException("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;
|
AbstractEntityDraft<E> draft = (AbstractEntityDraft<E>) drafted;
|
||||||
UpdateOperation update = new UpdateOperation<E>(this, draft);
|
UpdateOperation update = new UpdateOperation<E>(this, draft);
|
||||||
Map<String, Object> map = draft.toMap();
|
Map<String, Object> map = draft.toMap();
|
||||||
Set<String> mutatedProperties = draft.mutated();
|
Set<String> mutatedProperties = draft.mutated();
|
||||||
HelenusEntity entity = Helenus.entity(draft.getEntityClass());
|
HelenusEntity entity = Helenus.entity(draft.getEntityClass());
|
||||||
|
|
||||||
// Add all the mutated values contained in the draft.
|
// Add all the mutated values contained in the draft.
|
||||||
entity.getOrderedProperties().forEach(property -> {
|
entity
|
||||||
switch (property.getColumnType()) {
|
.getOrderedProperties()
|
||||||
case PARTITION_KEY:
|
.forEach(
|
||||||
case CLUSTERING_COLUMN:
|
property -> {
|
||||||
break;
|
switch (property.getColumnType()) {
|
||||||
default:
|
case PARTITION_KEY:
|
||||||
String propertyName = property.getPropertyName();
|
case CLUSTERING_COLUMN:
|
||||||
if (mutatedProperties.contains(propertyName)) {
|
break;
|
||||||
Object value = map.get(propertyName);
|
default:
|
||||||
Getter<Object> getter = new Getter<Object>() {
|
String propertyName = property.getPropertyName();
|
||||||
@Override
|
if (mutatedProperties.contains(propertyName)) {
|
||||||
public Object get() {
|
Object value = map.get(propertyName);
|
||||||
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
|
Getter<Object> getter =
|
||||||
|
new Getter<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object get() {
|
||||||
|
throw new DslPropertyException(
|
||||||
|
new HelenusPropertyNode(property, Optional.empty()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
update.set(getter, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
update.set(getter, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the partition and clustering keys if they were in the draft (normally the case).
|
// Add the partition and clustering keys if they were in the draft (normally the case).
|
||||||
entity.getOrderedProperties().forEach(property -> {
|
entity
|
||||||
switch (property.getColumnType()) {
|
.getOrderedProperties()
|
||||||
case PARTITION_KEY:
|
.forEach(
|
||||||
case CLUSTERING_COLUMN:
|
property -> {
|
||||||
String propertyName = property.getPropertyName();
|
switch (property.getColumnType()) {
|
||||||
Object value = map.get(propertyName);
|
case PARTITION_KEY:
|
||||||
Getter<Object> getter = new Getter<Object>() {
|
case CLUSTERING_COLUMN:
|
||||||
@Override
|
String propertyName = property.getPropertyName();
|
||||||
public Object get() {
|
Object value = map.get(propertyName);
|
||||||
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
|
Getter<Object> getter =
|
||||||
}
|
new Getter<Object>() {
|
||||||
};
|
@Override
|
||||||
update.where(getter, eq(value));
|
public Object get() {
|
||||||
}
|
throw new DslPropertyException(
|
||||||
});
|
new HelenusPropertyNode(property, Optional.empty()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
update.where(getter, eq(value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
@ -478,9 +498,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> InsertOperation<T> insert(T pojo) {
|
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;
|
HelenusEntity entity = null;
|
||||||
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
|
try {
|
||||||
|
entity = Helenus.resolve(pojo);
|
||||||
|
} catch (HelenusMappingException e) {
|
||||||
|
}
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
return new InsertOperation<T>(this, entity.getMappingInterface(), true);
|
return new InsertOperation<T>(this, entity.getMappingInterface(), true);
|
||||||
} else {
|
} 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) {
|
private <T> InsertOperation<T> insert(T pojo, Set<String> mutations) {
|
||||||
Objects.requireNonNull(pojo, "pojo is empty");
|
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) {
|
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;
|
HelenusEntity entity = null;
|
||||||
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
|
try {
|
||||||
|
entity = Helenus.resolve(pojo);
|
||||||
|
} catch (HelenusMappingException e) {
|
||||||
|
}
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
return new InsertOperation<T>(this, entity.getMappingInterface(), false);
|
return new InsertOperation<T>(this, entity.getMappingInterface(), false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -587,5 +619,4 @@ public final class HelenusSession extends AbstractSessionOperations implements C
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class PostCommitFunction<T, R> implements java.util.function.Function<T, R> {
|
public class PostCommitFunction<T, R> implements java.util.function.Function<T, R> {
|
||||||
|
|
||||||
private final UnitOfWork uow;
|
private final UnitOfWork uow;
|
||||||
private final List<CommitThunk> postCommit;
|
private final List<CommitThunk> postCommit;
|
||||||
|
|
||||||
PostCommitFunction(UnitOfWork uow, List<CommitThunk> postCommit) {
|
PostCommitFunction(UnitOfWork uow, List<CommitThunk> postCommit) {
|
||||||
this.uow = uow;
|
this.uow = uow;
|
||||||
this.postCommit = postCommit;
|
this.postCommit = postCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void andThen(CommitThunk after) {
|
public void andThen(CommitThunk after) {
|
||||||
Objects.requireNonNull(after);
|
Objects.requireNonNull(after);
|
||||||
if (postCommit == null) {
|
if (postCommit == null) {
|
||||||
after.apply();
|
after.apply();
|
||||||
} else {
|
} else {
|
||||||
postCommit.add(after);
|
postCommit.add(after);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public R apply(T t) {
|
public R apply(T t) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.*;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import net.helenus.core.reflect.DslExportable;
|
import net.helenus.core.reflect.DslExportable;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusEntityType;
|
import net.helenus.mapping.HelenusEntityType;
|
||||||
|
@ -131,12 +130,12 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionInitializer idempotentQueryExecution(boolean idempotent) {
|
public SessionInitializer idempotentQueryExecution(boolean idempotent) {
|
||||||
this.idempotent = idempotent;
|
this.idempotent = idempotent;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDefaultQueryIdempotency() {
|
public boolean getDefaultQueryIdempotency() {
|
||||||
return idempotent;
|
return idempotent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -185,9 +184,10 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
PackageUtil.getClasses(packageName)
|
PackageUtil.getClasses(packageName)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(c -> c.isInterface() && !c.isAnnotation())
|
.filter(c -> c.isInterface() && !c.isAnnotation())
|
||||||
.forEach(clazz -> {
|
.forEach(
|
||||||
initList.add(Either.right(clazz));
|
clazz -> {
|
||||||
});
|
initList.add(Either.right(clazz));
|
||||||
|
});
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
throw new HelenusException("fail to add package " + packageName, e);
|
throw new HelenusException("fail to add package " + packageName, e);
|
||||||
}
|
}
|
||||||
|
@ -267,18 +267,19 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
|
|
||||||
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
|
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
|
||||||
|
|
||||||
initList.forEach((either) -> {
|
initList.forEach(
|
||||||
Class<?> iface = null;
|
(either) -> {
|
||||||
if (either.isLeft()) {
|
Class<?> iface = null;
|
||||||
|
if (either.isLeft()) {
|
||||||
iface = MappingUtil.getMappingInterface(either.getLeft());
|
iface = MappingUtil.getMappingInterface(either.getLeft());
|
||||||
} else {
|
} else {
|
||||||
iface = either.getRight();
|
iface = either.getRight();
|
||||||
}
|
}
|
||||||
|
|
||||||
DslExportable dsl = (DslExportable) Helenus.dsl(iface);
|
DslExportable dsl = (DslExportable) Helenus.dsl(iface);
|
||||||
dsl.setMetadata(session.getCluster().getMetadata());
|
dsl.setMetadata(session.getCluster().getMetadata());
|
||||||
sessionRepository.add(dsl);
|
sessionRepository.add(dsl);
|
||||||
});
|
});
|
||||||
|
|
||||||
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
|
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
|
||||||
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);
|
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);
|
||||||
|
|
|
@ -15,44 +15,42 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import net.helenus.support.Either;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface UnitOfWork<E extends Exception> extends AutoCloseable {
|
public interface UnitOfWork<E extends Exception> extends AutoCloseable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the beginning of a transactional section of work. Will write a record to the shared
|
* Marks the beginning of a transactional section of work. Will write a record to the shared
|
||||||
* write-ahead log.
|
* write-ahead log.
|
||||||
*
|
*
|
||||||
* @return the handle used to commit or abort the work.
|
* @return the handle used to commit or abort the work.
|
||||||
*/
|
*/
|
||||||
UnitOfWork begin();
|
UnitOfWork begin();
|
||||||
|
|
||||||
UnitOfWork addNestedUnitOfWork(UnitOfWork uow);
|
UnitOfWork addNestedUnitOfWork(UnitOfWork uow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if the work performed between calling begin and now can be committed or not.
|
* Checks to see if the work performed between calling begin and now can be committed or not.
|
||||||
*
|
*
|
||||||
* @return a function from which to chain work that only happens when commit is successful
|
* @return a function from which to chain work that only happens when commit is successful
|
||||||
* @throws E when the work overlaps with other concurrent writers.
|
* @throws E when the work overlaps with other concurrent writers.
|
||||||
*/
|
*/
|
||||||
PostCommitFunction<Void, Void> commit() throws E;
|
PostCommitFunction<Void, Void> commit() throws E;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Explicitly abort the work within this unit of work. Any nested aborted unit of work
|
* Explicitly abort the work within this unit of work. Any nested aborted unit of work will
|
||||||
* will trigger the entire unit of work to commit.
|
* trigger the entire unit of work to commit.
|
||||||
*/
|
*/
|
||||||
void abort();
|
void abort();
|
||||||
|
|
||||||
|
boolean hasAborted();
|
||||||
|
|
||||||
boolean hasAborted();
|
boolean hasCommitted();
|
||||||
|
|
||||||
boolean hasCommitted();
|
//Either<Object, Set<Object>> cacheLookup(String key);
|
||||||
|
Set<Object> cacheLookup(String key);
|
||||||
|
|
||||||
//Either<Object, Set<Object>> cacheLookup(String key);
|
Map<String, Set<Object>> getCache();
|
||||||
Set<Object> cacheLookup(String key);
|
|
||||||
|
|
||||||
Map<String, Set<Object>> getCache();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,8 @@ import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
class UnitOfWorkImpl extends AbstractUnitOfWork<HelenusException> {
|
class UnitOfWorkImpl extends AbstractUnitOfWork<HelenusException> {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
|
public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
|
||||||
super(session, (AbstractUnitOfWork<HelenusException>) parent);
|
super(session, (AbstractUnitOfWork<HelenusException>) parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,7 @@ import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public class EntityIdentifyingFacet extends Facet {
|
public class EntityIdentifyingFacet extends Facet {
|
||||||
|
|
||||||
public EntityIdentifyingFacet(HelenusProperty prop) {
|
public EntityIdentifyingFacet(HelenusProperty prop) {}
|
||||||
|
|
||||||
}
|
public EntityIdentifyingFacet(HelenusProperty[]... props) {}
|
||||||
|
|
||||||
public EntityIdentifyingFacet(HelenusProperty[]... props) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package net.helenus.core.cache;
|
package net.helenus.core.cache;
|
||||||
|
|
||||||
public class Facet {
|
public class Facet {}
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
An Entity is identifiable via one or more Facets
|
An Entity is identifiable via one or more Facets
|
||||||
|
|
|
@ -19,11 +19,11 @@ 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 java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
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> {
|
extends AbstractOptionalOperation<E, O> {
|
||||||
|
|
||||||
protected Map<HelenusProperty, Filter<?>> filters = null;
|
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||||
|
|
|
@ -19,11 +19,11 @@ 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 java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
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> {
|
extends AbstractStreamOperation<E, O> {
|
||||||
|
|
||||||
protected Map<HelenusProperty, Filter<?>> filters = null;
|
protected Map<HelenusProperty, Filter<?>> filters = null;
|
||||||
|
|
|
@ -17,8 +17,6 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.UnitOfWork;
|
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);
|
return new PreparedOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public E sync() {
|
public E sync() {
|
||||||
final Timer.Context context = requestLatency.time();
|
final Timer.Context context = requestLatency.time();
|
||||||
try {
|
try {
|
||||||
|
@ -72,5 +69,4 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
||||||
if (uow == null) return async();
|
if (uow == null) return async();
|
||||||
return CompletableFuture.<E>supplyAsync(() -> sync(uow));
|
return CompletableFuture.<E>supplyAsync(() -> sync(uow));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ import net.helenus.support.HelenusException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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());
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
@ -55,7 +56,6 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
this.idempotent = sessionOperations.getDefaultQueryIdempotency();
|
this.idempotent = sessionOperations.getDefaultQueryIdempotency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public O ignoreCache(boolean enabled) {
|
public O ignoreCache(boolean enabled) {
|
||||||
enableCache = enabled;
|
enableCache = enabled;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
|
@ -93,8 +93,8 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
}
|
}
|
||||||
|
|
||||||
public O isIdempotent(boolean idempotent) {
|
public O isIdempotent(boolean idempotent) {
|
||||||
this.idempotent = idempotent;
|
this.idempotent = idempotent;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O downgradingConsistencyRetryPolicy() {
|
public O downgradingConsistencyRetryPolicy() {
|
||||||
|
@ -232,7 +232,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idempotent) {
|
if (idempotent) {
|
||||||
statement.setIdempotent(true);
|
statement.setIdempotent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
|
|
|
@ -21,20 +21,11 @@ import com.datastax.driver.core.ResultSet;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
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.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.UnitOfWork;
|
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>>
|
public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> {
|
extends AbstractStatementOperation<E, O> {
|
||||||
|
@ -113,5 +104,4 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
if (uow == null) return async();
|
if (uow == null) return async();
|
||||||
return CompletableFuture.<Stream<E>>supplyAsync(() -> sync(uow));
|
return CompletableFuture.<Stream<E>>supplyAsync(() -> sync(uow));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,9 @@ public final class BoundOptionalOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<E> transform(ResultSet resultSet) { return delegate.transform(resultSet); }
|
public Optional<E> transform(ResultSet resultSet) {
|
||||||
|
return delegate.transform(resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement(boolean cached) {
|
public Statement buildStatement(boolean cached) {
|
||||||
|
|
|
@ -26,14 +26,17 @@ public final class BoundStreamOperation<E>
|
||||||
private final BoundStatement boundStatement;
|
private final BoundStatement boundStatement;
|
||||||
private final AbstractStreamOperation<E, ?> delegate;
|
private final AbstractStreamOperation<E, ?> delegate;
|
||||||
|
|
||||||
public BoundStreamOperation(BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
public BoundStreamOperation(
|
||||||
|
BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
||||||
super(operation.sessionOps);
|
super(operation.sessionOps);
|
||||||
this.boundStatement = boundStatement;
|
this.boundStatement = boundStatement;
|
||||||
this.delegate = operation;
|
this.delegate = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
public String getStatementCacheKey() {
|
||||||
|
return delegate.getStatementCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<E> transform(ResultSet resultSet) {
|
public Stream<E> transform(ResultSet resultSet) {
|
||||||
|
@ -41,5 +44,7 @@ public final class BoundStreamOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.BuiltStatement;
|
||||||
import com.datastax.driver.core.querybuilder.Insert;
|
import com.datastax.driver.core.querybuilder.Insert;
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Getter;
|
import net.helenus.core.Getter;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
|
@ -41,7 +40,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
|
|
||||||
private HelenusEntity entity;
|
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 T pojo;
|
||||||
private final Class<?> resultType;
|
private final Class<?> resultType;
|
||||||
private boolean ifNotExists;
|
private boolean ifNotExists;
|
||||||
|
@ -57,7 +57,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
this.resultType = ResultSet.class;
|
this.resultType = ResultSet.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertOperation(AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) {
|
public InsertOperation(
|
||||||
|
AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
this.ifNotExists = ifNotExists;
|
this.ifNotExists = ifNotExists;
|
||||||
|
@ -172,7 +173,7 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
// Some values man need to be converted (e.g. from String to Enum). This is done
|
// Some values man need to be converted (e.g. from String to Enum). This is done
|
||||||
// within the BeanColumnValueProvider below.
|
// within the BeanColumnValueProvider below.
|
||||||
Optional<Function<Object, Object>> converter =
|
Optional<Function<Object, Object>> converter =
|
||||||
prop.getReadConverter(sessionOps.getSessionRepository());
|
prop.getReadConverter(sessionOps.getSessionRepository());
|
||||||
if (converter.isPresent()) {
|
if (converter.isPresent()) {
|
||||||
backingMap.put(key, converter.get().apply(backingMap.get(key)));
|
backingMap.put(key, converter.get().apply(backingMap.get(key)));
|
||||||
}
|
}
|
||||||
|
@ -232,23 +233,25 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
public String getStatementCacheKey() {
|
public String getStatementCacheKey() {
|
||||||
List<String> keys = new ArrayList<>(values.size());
|
List<String> keys = new ArrayList<>(values.size());
|
||||||
values.forEach(
|
values.forEach(
|
||||||
t -> {
|
t -> {
|
||||||
HelenusPropertyNode prop = t._1;
|
HelenusPropertyNode prop = t._1;
|
||||||
switch (prop.getProperty().getColumnType()) {
|
switch (prop.getProperty().getColumnType()) {
|
||||||
case PARTITION_KEY:
|
case PARTITION_KEY:
|
||||||
case CLUSTERING_COLUMN:
|
case CLUSTERING_COLUMN:
|
||||||
keys.add(prop.getColumnName() + "==" + t._2.toString());
|
keys.add(prop.getColumnName() + "==" + t._2.toString());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return entity.getName() + ": " + Joiner.on(",").join(keys);
|
return entity.getName() + ": " + Joiner.on(",").join(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T sync(UnitOfWork uow) {
|
public T sync(UnitOfWork uow) {
|
||||||
if (uow == null) { return sync(); }
|
if (uow == null) {
|
||||||
|
return sync();
|
||||||
|
}
|
||||||
T result = super.sync(uow);
|
T result = super.sync(uow);
|
||||||
Class<?> iface = entity.getMappingInterface();
|
Class<?> iface = entity.getMappingInterface();
|
||||||
if (resultType == iface) {
|
if (resultType == iface) {
|
||||||
|
@ -261,5 +264,4 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +1,81 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.Set;
|
import brave.Span;
|
||||||
import java.util.concurrent.ExecutionException;
|
import brave.Tracer;
|
||||||
|
import brave.propagation.TraceContext;
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import com.datastax.driver.core.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.Set;
|
||||||
import brave.Span;
|
import java.util.concurrent.ExecutionException;
|
||||||
import brave.Tracer;
|
|
||||||
import brave.propagation.TraceContext;
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
import net.helenus.core.cache.EntityIdentifyingFacet;
|
import net.helenus.core.cache.EntityIdentifyingFacet;
|
||||||
|
|
||||||
public abstract class Operation<E> {
|
public abstract class Operation<E> {
|
||||||
|
|
||||||
protected final AbstractSessionOperations sessionOps;
|
protected final AbstractSessionOperations sessionOps;
|
||||||
protected final Meter uowCacheHits;
|
protected final Meter uowCacheHits;
|
||||||
protected final Meter uowCacheMiss;
|
protected final Meter uowCacheMiss;
|
||||||
protected final Timer requestLatency;
|
protected final Timer requestLatency;
|
||||||
|
|
||||||
Operation(AbstractSessionOperations sessionOperations) {
|
Operation(AbstractSessionOperations sessionOperations) {
|
||||||
this.sessionOps = sessionOperations;
|
this.sessionOps = sessionOperations;
|
||||||
MetricRegistry metrics = sessionOperations.getMetricRegistry();
|
MetricRegistry metrics = sessionOperations.getMetricRegistry();
|
||||||
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
|
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
|
||||||
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
|
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
|
||||||
this.requestLatency = metrics.timer("net.helenus.request-latency");
|
this.requestLatency = metrics.timer("net.helenus.request-latency");
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
Span span = null;
|
||||||
|
if (tracer != null && traceContext != null) {
|
||||||
|
span = tracer.newChild(traceContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, boolean showValues, boolean cached) {
|
try {
|
||||||
|
|
||||||
// Start recording in a Zipkin sub-span our execution time to perform this operation.
|
if (span != null) {
|
||||||
Tracer tracer = session.getZipkinTracer();
|
span.name("cassandra");
|
||||||
Span span = null;
|
span.start();
|
||||||
if (tracer != null && traceContext != null) {
|
}
|
||||||
span = tracer.newChild(traceContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
Statement statement = options(buildStatement(cached));
|
||||||
|
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
||||||
|
return futureResultSet.get();
|
||||||
|
|
||||||
if (span != null) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
span.name("cassandra");
|
|
||||||
span.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement statement = options(buildStatement(cached));
|
throw new RuntimeException(e);
|
||||||
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
|
||||||
return futureResultSet.get();
|
|
||||||
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} finally {
|
||||||
|
|
||||||
throw new RuntimeException(e);
|
if (span != null) {
|
||||||
|
span.finish();
|
||||||
} finally {
|
}
|
||||||
|
|
||||||
if (span != null) {
|
|
||||||
span.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Statement options(Statement statement) { return statement; }
|
public Statement options(Statement statement) {
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
public Statement buildStatement(boolean cached) { return null; }
|
public Statement buildStatement(boolean cached) {
|
||||||
|
return null;
|
||||||
public Set<EntityIdentifyingFacet> getIdentifyingFacets() { return null; }
|
}
|
||||||
|
|
||||||
|
public Set<EntityIdentifyingFacet> getIdentifyingFacets() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.BoundStatement;
|
import com.datastax.driver.core.BoundStatement;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public final class PreparedStreamOperation<E> {
|
public final class PreparedStreamOperation<E> {
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,9 @@ public final class SelectFirstOperation<E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
public String getStatementCacheKey() {
|
||||||
|
return delegate.getStatementCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement(boolean cached) {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
|
@ -36,7 +36,9 @@ public final class SelectFirstTransformingOperation<R, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
public String getStatementCacheKey() {
|
||||||
|
return delegate.getStatementCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement(boolean cached) {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
|
|
@ -22,15 +22,12 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
import com.datastax.driver.core.querybuilder.Select;
|
import com.datastax.driver.core.querybuilder.Select;
|
||||||
import com.datastax.driver.core.querybuilder.Select.Selection;
|
import com.datastax.driver.core.querybuilder.Select.Selection;
|
||||||
import com.datastax.driver.core.querybuilder.Select.Where;
|
import com.datastax.driver.core.querybuilder.Select.Where;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import java.util.*;
|
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.cache.Facet;
|
|
||||||
import net.helenus.core.cache.EntityIdentifyingFacet;
|
import net.helenus.core.cache.EntityIdentifyingFacet;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
@ -56,7 +53,7 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
this.rowMapper =
|
this.rowMapper =
|
||||||
new Function<Row, E>() {
|
new Function<Row, E>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E apply(Row source) {
|
public E apply(Row source) {
|
||||||
|
@ -188,20 +185,25 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
final Set<EntityIdentifyingFacet> facets = new HashSet<>(filters.size());
|
final Set<EntityIdentifyingFacet> facets = new HashSet<>(filters.size());
|
||||||
// Check to see if this select statement has enough information to build one or
|
// Check to see if this select statement has enough information to build one or
|
||||||
// more identifying facets.
|
// more identifying facets.
|
||||||
entity.getIdentityFacets().forEach((facetName, facet) -> {
|
entity
|
||||||
EntityIdentifyingFacet boundFacet = null;
|
.getIdentityFacets()
|
||||||
if (!facet.isFullyBound()) {
|
.forEach(
|
||||||
boundFacet = new EntityIdentifyingFacet(facet);
|
(facetName, facet) -> {
|
||||||
for (HelenusProperty prop : facet.getUnboundEntityProperties()) {
|
EntityIdentifyingFacet boundFacet = null;
|
||||||
Filter filter = filters.get(facet.getProperty());
|
if (!facet.isFullyBound()) {
|
||||||
if (filter == null) { break; }
|
boundFacet = new EntityIdentifyingFacet(facet);
|
||||||
boundFacet.setValueForProperty(prop, filter.toString());
|
for (HelenusProperty prop : facet.getUnboundEntityProperties()) {
|
||||||
}
|
Filter filter = filters.get(facet.getProperty());
|
||||||
}
|
if (filter == null) {
|
||||||
if (boundFacet != null && boundFacet.isFullyBound()) {
|
break;
|
||||||
facets.add(boundFacet);
|
}
|
||||||
}
|
boundFacet.setValueForProperty(prop, filter.toString());
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
if (boundFacet != null && boundFacet.isFullyBound()) {
|
||||||
|
facets.add(boundFacet);
|
||||||
|
}
|
||||||
|
});
|
||||||
return facets;
|
return facets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,14 +225,14 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
entity = prop.getEntity();
|
entity = prop.getEntity();
|
||||||
} else if (entity != prop.getEntity()) {
|
} else if (entity != prop.getEntity()) {
|
||||||
throw new HelenusMappingException(
|
throw new HelenusMappingException(
|
||||||
"you can select columns only from a single entity "
|
"you can select columns only from a single entity "
|
||||||
+ entity.getMappingInterface()
|
+ entity.getMappingInterface()
|
||||||
+ " or "
|
+ " or "
|
||||||
+ prop.getEntity().getMappingInterface());
|
+ prop.getEntity().getMappingInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
switch(prop.getProperty().getColumnType()) {
|
switch (prop.getProperty().getColumnType()) {
|
||||||
case PARTITION_KEY:
|
case PARTITION_KEY:
|
||||||
case CLUSTERING_COLUMN:
|
case CLUSTERING_COLUMN:
|
||||||
break;
|
break;
|
||||||
|
@ -288,10 +290,14 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
@Override
|
@Override
|
||||||
public Stream<E> transform(ResultSet resultSet) {
|
public Stream<E> transform(ResultSet resultSet) {
|
||||||
if (rowMapper != null) {
|
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 {
|
} else {
|
||||||
return (Stream<E>)
|
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
|
@Override
|
||||||
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
|
public String getStatementCacheKey() {
|
||||||
|
return delegate.getStatementCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement(boolean cached) {
|
public BuiltStatement buildStatement(boolean cached) {
|
||||||
|
@ -47,5 +49,4 @@ public final class SelectTransformingOperation<R, E>
|
||||||
public Stream<R> transform(ResultSet resultSet) {
|
public Stream<R> transform(ResultSet resultSet) {
|
||||||
return delegate.transform(resultSet).map(fn);
|
return delegate.transform(resultSet).map(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.querybuilder.Assignment;
|
import com.datastax.driver.core.querybuilder.Assignment;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
import com.datastax.driver.core.querybuilder.Update;
|
import com.datastax.driver.core.querybuilder.Update;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
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;
|
||||||
|
@ -43,19 +41,21 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
private int[] ttl;
|
private int[] ttl;
|
||||||
private long[] timestamp;
|
private long[] timestamp;
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations){
|
public UpdateOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.draft = null;
|
this.draft = null;
|
||||||
this.draftMap = null;
|
this.draftMap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) {
|
public UpdateOperation(
|
||||||
|
AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.draft = draft;
|
this.draft = draft;
|
||||||
this.draftMap = draft.toMap();
|
this.draftMap = draft.toMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
public UpdateOperation(
|
||||||
|
AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.draft = null;
|
this.draft = null;
|
||||||
this.draftMap = null;
|
this.draftMap = null;
|
||||||
|
@ -152,7 +152,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>)draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.add(0, value);
|
list.add(0, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>)draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
list.add(0, value);
|
list.add(0, value);
|
||||||
} else if (idx > list.size()) {
|
} else if (idx > list.size()) {
|
||||||
|
@ -222,7 +222,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
String key = p.getProperty().getPropertyName();
|
String key = p.getProperty().getPropertyName();
|
||||||
List<V> list = (List<V>)draftMap.get(key);
|
List<V> list = (List<V>) draftMap.get(key);
|
||||||
list.add(value);
|
list.add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +579,9 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E sync(UnitOfWork uow) {
|
public E sync(UnitOfWork uow) {
|
||||||
if (uow == null) { return sync(); }
|
if (uow == null) {
|
||||||
|
return sync();
|
||||||
|
}
|
||||||
E result = super.sync(uow);
|
E result = super.sync(uow);
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
String key = getStatementCacheKey();
|
String key = getStatementCacheKey();
|
||||||
|
@ -591,5 +593,4 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
import net.helenus.mapping.HelenusEntity;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
|
@ -67,46 +67,46 @@ public class DslInvocationHandler<E> implements InvocationHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HelenusEntity init(Metadata metadata) {
|
private HelenusEntity init(Metadata metadata) {
|
||||||
HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
|
HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
|
|
||||||
map.put(prop.getGetterMethod(), prop);
|
map.put(prop.getGetterMethod(), prop);
|
||||||
|
|
||||||
AbstractDataType type = prop.getDataType();
|
AbstractDataType type = prop.getDataType();
|
||||||
Class<?> javaType = prop.getJavaType();
|
Class<?> javaType = prop.getJavaType();
|
||||||
|
|
||||||
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
|
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
|
||||||
|
|
||||||
Object childDsl =
|
Object childDsl =
|
||||||
Helenus.dsl(
|
Helenus.dsl(
|
||||||
javaType,
|
javaType,
|
||||||
classLoader,
|
classLoader,
|
||||||
Optional.of(new HelenusPropertyNode(prop, parent)),
|
Optional.of(new HelenusPropertyNode(prop, parent)),
|
||||||
metadata);
|
metadata);
|
||||||
|
|
||||||
udtMap.put(prop.getGetterMethod(), childDsl);
|
udtMap.put(prop.getGetterMethod(), childDsl);
|
||||||
}
|
|
||||||
|
|
||||||
if (type instanceof DTDataType) {
|
|
||||||
DTDataType dataType = (DTDataType) type;
|
|
||||||
|
|
||||||
if (dataType.getDataType() instanceof TupleType
|
|
||||||
&& !TupleValue.class.isAssignableFrom(javaType)) {
|
|
||||||
|
|
||||||
Object childDsl =
|
|
||||||
Helenus.dsl(
|
|
||||||
javaType,
|
|
||||||
classLoader,
|
|
||||||
Optional.of(new HelenusPropertyNode(prop, parent)),
|
|
||||||
metadata);
|
|
||||||
|
|
||||||
tupleMap.put(prop.getGetterMethod(), childDsl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return entity;
|
if (type instanceof DTDataType) {
|
||||||
|
DTDataType dataType = (DTDataType) type;
|
||||||
|
|
||||||
|
if (dataType.getDataType() instanceof TupleType
|
||||||
|
&& !TupleValue.class.isAssignableFrom(javaType)) {
|
||||||
|
|
||||||
|
Object childDsl =
|
||||||
|
Helenus.dsl(
|
||||||
|
javaType,
|
||||||
|
classLoader,
|
||||||
|
Optional.of(new HelenusPropertyNode(prop, parent)),
|
||||||
|
metadata);
|
||||||
|
|
||||||
|
tupleMap.put(prop.getGetterMethod(), childDsl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -127,10 +127,10 @@ public class DslInvocationHandler<E> implements InvocationHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DslExportable.SET_METADATA_METHOD.equals(methodName)
|
if (DslExportable.SET_METADATA_METHOD.equals(methodName)
|
||||||
&& args.length == 1
|
&& args.length == 1
|
||||||
&& args[0] instanceof Metadata) {
|
&& args[0] instanceof Metadata) {
|
||||||
if (metadata == null) {
|
if (metadata == null) {
|
||||||
this.setMetadata((Metadata) args[0]);
|
this.setMetadata((Metadata) args[0]);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.mapping.annotation.Transient;
|
import net.helenus.mapping.annotation.Transient;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
@ -94,7 +93,7 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("dsl".equals(methodName)) {
|
if ("dsl".equals(methodName)) {
|
||||||
return Helenus.dsl(iface);
|
return Helenus.dsl(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
||||||
|
|
|
@ -15,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
import net.helenus.core.cache.EntityIdentifyingFacet;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import net.helenus.core.cache.EntityIdentifyingFacet;
|
||||||
|
|
||||||
public interface HelenusEntity {
|
public interface HelenusEntity {
|
||||||
|
|
||||||
|
@ -35,5 +34,4 @@ public interface HelenusEntity {
|
||||||
HelenusProperty getProperty(String name);
|
HelenusProperty getProperty(String name);
|
||||||
|
|
||||||
Map<String, EntityIdentifyingFacet> getIdentityFacets();
|
Map<String, EntityIdentifyingFacet> getIdentityFacets();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import net.helenus.config.HelenusSettings;
|
import net.helenus.config.HelenusSettings;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.annotation.Cacheable;
|
import net.helenus.core.annotation.Cacheable;
|
||||||
|
@ -60,21 +59,22 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
||||||
|
|
||||||
Map<String, Method> methods = new HashMap<String, Method>();
|
Map<String, Method> methods = new HashMap<String, Method>();
|
||||||
for (Method m : iface.getDeclaredMethods()) {
|
for (Method m : iface.getDeclaredMethods()) {
|
||||||
methods.put(m.getName(), m);
|
methods.put(m.getName(), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Class<?> c : ClassUtils.getAllInterfaces(iface)) {
|
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()) {
|
for (Method m : c.getDeclaredMethods()) {
|
||||||
Method o = methods.get(m.getName());
|
Method o = methods.get(m.getName());
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
// Prefer overridden method implementation.
|
// Prefer overridden method implementation.
|
||||||
if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) {
|
if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) {
|
||||||
methods.put(m.getName(), m);
|
methods.put(m.getName(), m);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
methods.put(m.getName(), m);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
methods.put(m.getName(), m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,27 +110,34 @@ public final class HelenusMappingEntity implements HelenusEntity {
|
||||||
cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class));
|
cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class));
|
||||||
|
|
||||||
ImmutableMap.Builder<String, EntityIdentifyingFacet> allFacetsBuilder = ImmutableMap.builder();
|
ImmutableMap.Builder<String, EntityIdentifyingFacet> allFacetsBuilder = ImmutableMap.builder();
|
||||||
ImmutableMap.Builder<String, EntityIdentifyingFacet> ancillaryFacetsBuilder = ImmutableMap.builder();
|
ImmutableMap.Builder<String, EntityIdentifyingFacet> ancillaryFacetsBuilder =
|
||||||
|
ImmutableMap.builder();
|
||||||
EntityIdentifyingFacet primaryFacet = null;
|
EntityIdentifyingFacet primaryFacet = null;
|
||||||
List<HelenusProperty> primaryProperties = new ArrayList<HelenusProperty>(4);
|
List<HelenusProperty> primaryProperties = new ArrayList<HelenusProperty>(4);
|
||||||
for (HelenusProperty prop : propsLocal) {
|
for (HelenusProperty prop : propsLocal) {
|
||||||
switch(prop.getColumnType()) {
|
switch (prop.getColumnType()) {
|
||||||
case PARTITION_KEY:
|
case PARTITION_KEY:
|
||||||
case CLUSTERING_COLUMN:
|
case CLUSTERING_COLUMN:
|
||||||
primaryProperties.add(prop);
|
primaryProperties.add(prop);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (primaryProperties != null) {
|
if (primaryProperties != null) {
|
||||||
primaryFacet = new EntityIdentifyingFacet(keyspace, table, schemaVersion, primaryProperties.toArray(new HelenusProperty[props.size()]));
|
primaryFacet =
|
||||||
allFacetsBuilder.put("*", primaryFacet);
|
new EntityIdentifyingFacet(
|
||||||
primaryProperties = null;
|
keyspace,
|
||||||
}
|
table,
|
||||||
Optional<IdentityName> optionalIndexName = prop.getIndexName();
|
schemaVersion,
|
||||||
if (optionalIndexName.isPresent()) {
|
primaryProperties.toArray(new HelenusProperty[props.size()]));
|
||||||
EntityIdentifyingFacet facet = new EntityIdentifyingFacet(keyspace, table, schemaVersion, prop);
|
allFacetsBuilder.put("*", primaryFacet);
|
||||||
ancillaryFacetsBuilder.put(prop.getPropertyName(), facet);
|
primaryProperties = null;
|
||||||
}
|
}
|
||||||
}
|
Optional<IdentityName> optionalIndexName = prop.getIndexName();
|
||||||
|
if (optionalIndexName.isPresent()) {
|
||||||
|
EntityIdentifyingFacet facet =
|
||||||
|
new EntityIdentifyingFacet(keyspace, table, schemaVersion, prop);
|
||||||
|
ancillaryFacetsBuilder.put(prop.getPropertyName(), facet);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.primaryIdentityFacet = primaryFacet;
|
this.primaryIdentityFacet = primaryFacet;
|
||||||
this.ancillaryIdentityFacets = ancillaryFacetsBuilder.build();
|
this.ancillaryIdentityFacets = ancillaryFacetsBuilder.build();
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.helenus.mapping.javatype;
|
||||||
|
|
||||||
public abstract class AbstractCollectionJavaType extends AbstractJavaType {
|
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 abstract class AbstractJavaType {
|
||||||
|
|
||||||
public static boolean isCollectionType() { return false; }
|
public static boolean isCollectionType() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Class<?> getJavaClass();
|
public abstract Class<?> getJavaClass();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ 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;
|
||||||
|
|
|
@ -4,10 +4,11 @@ import net.helenus.mapping.ColumnType;
|
||||||
|
|
||||||
public abstract class AbstractCollectionDataType extends AbstractDataType {
|
public abstract class AbstractCollectionDataType extends AbstractDataType {
|
||||||
|
|
||||||
public AbstractCollectionDataType(ColumnType columnType) {
|
public AbstractCollectionDataType(ColumnType columnType) {
|
||||||
super(columnType);
|
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);
|
"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.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;
|
||||||
|
|
|
@ -33,7 +33,7 @@ public enum BeanColumnValueProvider implements ColumnValueProvider {
|
||||||
try {
|
try {
|
||||||
value = getter.invoke(bean, new Object[] {});
|
value = getter.invoke(bean, new Object[] {});
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
if (e.getCause() != null ) {
|
if (e.getCause() != null) {
|
||||||
throw new HelenusException("getter threw an exception", e.getCause());
|
throw new HelenusException("getter threw an exception", e.getCause());
|
||||||
}
|
}
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
|
|
|
@ -67,11 +67,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual = session.<Customer>select(customer)
|
Customer actual =
|
||||||
.where(customer::id, eq(id))
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(aliases, actual.aliases());
|
Assert.assertEquals(aliases, actual.aliases());
|
||||||
Assert.assertNull(actual.names());
|
Assert.assertNull(actual.names());
|
||||||
|
@ -90,11 +87,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
|
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Customer>select(customer)
|
actual =
|
||||||
.where(customer::id, eq(id))
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(expected, actual.aliases());
|
Assert.assertEquals(expected, actual.aliases());
|
||||||
|
@ -170,11 +164,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual = session.<Customer>select(customer)
|
Customer actual =
|
||||||
.where(customer::id, eq(id))
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(names, actual.names());
|
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();
|
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Customer>select(customer)
|
actual =
|
||||||
.where(customer::id, eq(id))
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(expected, actual.names());
|
Assert.assertEquals(expected, actual.names());
|
||||||
|
@ -306,10 +294,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Customer actual = session.<Customer>select(customer)
|
Customer actual =
|
||||||
.where(customer::id, eq(id)).single()
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(props, actual.properties());
|
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();
|
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Customer>select(customer)
|
actual =
|
||||||
.where(customer::id, eq(id))
|
session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
Assert.assertEquals(expected, actual.properties());
|
Assert.assertEquals(expected, actual.properties());
|
||||||
|
|
||||||
|
|
|
@ -18,76 +18,73 @@ package net.helenus.test.integration.core.draft;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import net.helenus.core.Helenus;
|
||||||
|
import net.helenus.core.HelenusSession;
|
||||||
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
|
||||||
import net.helenus.core.HelenusSession;
|
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
|
||||||
|
|
||||||
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
|
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
|
static Supply supply;
|
||||||
|
static HelenusSession session;
|
||||||
|
|
||||||
static Supply supply;
|
@BeforeClass
|
||||||
static HelenusSession session;
|
public static void beforeTest() {
|
||||||
|
session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get();
|
||||||
|
supply = session.dsl(Supply.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFoo() throws Exception {
|
||||||
|
Supply.Draft draft = null;
|
||||||
|
|
||||||
@BeforeClass
|
draft =
|
||||||
public static void beforeTest() {
|
Supply.draft("APAC")
|
||||||
session = Helenus.init(getSession())
|
.code("WIDGET-002")
|
||||||
.showCql()
|
.description("Our second Widget!")
|
||||||
.add(Supply.class)
|
.demand(
|
||||||
.autoCreateDrop()
|
new HashMap<String, Long>() {
|
||||||
.get();
|
{
|
||||||
supply = session.dsl(Supply.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFoo() throws Exception {
|
|
||||||
Supply.Draft draft = null;
|
|
||||||
|
|
||||||
draft = Supply.draft("APAC")
|
|
||||||
.code("WIDGET-002")
|
|
||||||
.description("Our second Widget!")
|
|
||||||
.demand(new HashMap<String, Long>() {{
|
|
||||||
put("APAC", 100L);
|
put("APAC", 100L);
|
||||||
put("EMEA", 10000L);
|
put("EMEA", 10000L);
|
||||||
put("NORAM", 2000000L);
|
put("NORAM", 2000000L);
|
||||||
}})
|
}
|
||||||
.shipments(new HashSet<String>() {{
|
})
|
||||||
|
.shipments(
|
||||||
|
new HashSet<String>() {
|
||||||
|
{
|
||||||
add("HMS Puddle in transit to APAC, 100 units.");
|
add("HMS Puddle in transit to APAC, 100 units.");
|
||||||
add("Frigate Jimmy in transit to EMEA, 10000 units.");
|
add("Frigate Jimmy in transit to EMEA, 10000 units.");
|
||||||
}})
|
}
|
||||||
.suppliers(new ArrayList<String>() {{
|
})
|
||||||
|
.suppliers(
|
||||||
|
new ArrayList<String>() {
|
||||||
|
{
|
||||||
add("Puddle, Inc.");
|
add("Puddle, Inc.");
|
||||||
add("Jimmy Town, LTD.");
|
add("Jimmy Town, LTD.");
|
||||||
}});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Supply s1 = session.<Supply>insert(draft)
|
Supply s1 = session.<Supply>insert(draft).sync();
|
||||||
.sync();
|
|
||||||
|
|
||||||
// List
|
// List
|
||||||
Supply s2 = session.<Supply>update(s1.update())
|
Supply s2 =
|
||||||
.prepend(supply::suppliers, "Pignose Supply, LLC.")
|
session
|
||||||
.sync();
|
.<Supply>update(s1.update())
|
||||||
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
|
.prepend(supply::suppliers, "Pignose Supply, LLC.")
|
||||||
|
.sync();
|
||||||
|
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
|
||||||
|
|
||||||
// Set
|
// Set
|
||||||
String shipment = "Pignose, on the way! (1M units)";
|
String shipment = "Pignose, on the way! (1M units)";
|
||||||
Supply s3 = session.<Supply>update(s2.update())
|
Supply s3 = session.<Supply>update(s2.update()).add(supply::shipments, shipment).sync();
|
||||||
.add(supply::shipments, shipment)
|
Assert.assertTrue(s3.shipments().contains(shipment));
|
||||||
.sync();
|
|
||||||
Assert.assertTrue(s3.shipments().contains(shipment));
|
|
||||||
|
|
||||||
// Map
|
// Map
|
||||||
Supply s4 = session.<Supply>update(s3.update())
|
Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
|
||||||
.put(supply::demand, "NORAM", 10L)
|
Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
|
||||||
.sync();
|
}
|
||||||
Assert.assertEquals((long)s4.demand().get("NORAM"), 10L);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,78 +1,93 @@
|
||||||
package net.helenus.test.integration.core.draft;
|
package net.helenus.test.integration.core.draft;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.helenus.core.AbstractAuditedEntityDraft;
|
import net.helenus.core.AbstractAuditedEntityDraft;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Inventory {
|
public interface Inventory {
|
||||||
|
|
||||||
static Inventory inventory = Helenus.dsl(Inventory.class);
|
static Inventory inventory = Helenus.dsl(Inventory.class);
|
||||||
|
|
||||||
@PartitionKey UUID id();
|
@PartitionKey
|
||||||
@Column("emea") @Types.Counter long EMEA();
|
UUID id();
|
||||||
@Column("noram") @Types.Counter long NORAM();
|
|
||||||
@Column("apac") @Types.Counter long APAC();
|
|
||||||
|
|
||||||
@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();
|
||||||
|
|
||||||
class Draft extends AbstractAuditedEntityDraft<Inventory> {
|
@Transient
|
||||||
|
static Draft draft(UUID id) {
|
||||||
|
return new Draft(id);
|
||||||
|
}
|
||||||
|
|
||||||
// Entity/Draft pattern-enabling methods:
|
@Transient
|
||||||
Draft(UUID id) {
|
default Draft update() {
|
||||||
super(null);
|
return new Draft(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Primary Key:
|
class Draft extends AbstractAuditedEntityDraft<Inventory> {
|
||||||
set(inventory::id, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Draft(Inventory inventory) {
|
// Entity/Draft pattern-enabling methods:
|
||||||
super((MapExportable) inventory);
|
Draft(UUID id) {
|
||||||
}
|
super(null);
|
||||||
|
|
||||||
public Class<Inventory> getEntityClass() { return Inventory.class; }
|
|
||||||
|
|
||||||
protected String getCurrentAuditor() { return "unknown"; }
|
|
||||||
|
|
||||||
// Immutable properties:
|
|
||||||
public UUID id() {
|
|
||||||
return this.<UUID>get(inventory::id, UUID.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long EMEA() {
|
|
||||||
return this.<Long>get(inventory::EMEA, long.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft EMEA(long count) {
|
|
||||||
mutate(inventory::EMEA, count);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long APAC() {
|
|
||||||
return this.<Long>get(inventory::APAC, long.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft APAC(long count) {
|
|
||||||
mutate(inventory::APAC, count);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long NORAM() {
|
|
||||||
return this.<Long>get(inventory::NORAM, long.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft NORAM(long count) {
|
|
||||||
mutate(inventory::NORAM, count);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Primary Key:
|
||||||
|
set(inventory::id, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draft(Inventory inventory) {
|
||||||
|
super((MapExportable) inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<Inventory> getEntityClass() {
|
||||||
|
return Inventory.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCurrentAuditor() {
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Immutable properties:
|
||||||
|
public UUID id() {
|
||||||
|
return this.<UUID>get(inventory::id, UUID.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long EMEA() {
|
||||||
|
return this.<Long>get(inventory::EMEA, long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft EMEA(long count) {
|
||||||
|
mutate(inventory::EMEA, count);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long APAC() {
|
||||||
|
return this.<Long>get(inventory::APAC, long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft APAC(long count) {
|
||||||
|
mutate(inventory::APAC, count);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long NORAM() {
|
||||||
|
return this.<Long>get(inventory::NORAM, long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft NORAM(long count) {
|
||||||
|
mutate(inventory::NORAM, count);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,129 +1,145 @@
|
||||||
package net.helenus.test.integration.core.draft;
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.datastax.driver.core.utils.UUIDs;
|
|
||||||
|
|
||||||
import net.helenus.core.AbstractEntityDraft;
|
import net.helenus.core.AbstractEntityDraft;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
import net.helenus.core.reflect.MapExportable;
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
public interface Supply {
|
public interface Supply {
|
||||||
|
|
||||||
static Supply supply = Helenus.dsl(Supply.class);
|
static Supply supply = Helenus.dsl(Supply.class);
|
||||||
|
|
||||||
@PartitionKey UUID id();
|
@PartitionKey
|
||||||
@ClusteringColumn(ordinal=0) default String region() { return "NORAM"; }
|
UUID id();
|
||||||
|
|
||||||
@Index(caseSensitive = false) String code();
|
@ClusteringColumn(ordinal = 0)
|
||||||
@Index String description(); // @IndexText == lucene index
|
default String region() {
|
||||||
@Index Map<String, Long> demand();
|
return "NORAM";
|
||||||
@Index List<String> suppliers();
|
}
|
||||||
@Index Set<String> shipments();
|
|
||||||
|
|
||||||
@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();
|
||||||
|
|
||||||
class Draft extends AbstractEntityDraft<Supply> {
|
@Index
|
||||||
|
List<String> suppliers();
|
||||||
|
|
||||||
// Entity/Draft pattern-enabling methods:
|
@Index
|
||||||
Draft(String region) {
|
Set<String> shipments();
|
||||||
super(null);
|
|
||||||
|
|
||||||
// Primary Key:
|
@Transient
|
||||||
set(supply::id, UUIDs.timeBased());
|
static Draft draft(String region) {
|
||||||
set(supply::region, region);
|
return new Draft(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
Draft(Supply supply) {
|
@Transient
|
||||||
super((MapExportable) supply);
|
default Draft update() {
|
||||||
}
|
return new Draft(this);
|
||||||
|
}
|
||||||
|
|
||||||
public Class<Supply> getEntityClass() { return Supply.class; }
|
class Draft extends AbstractEntityDraft<Supply> {
|
||||||
|
|
||||||
// Immutable properties:
|
// Entity/Draft pattern-enabling methods:
|
||||||
public UUID id() {
|
Draft(String region) {
|
||||||
return this.<UUID>get(supply::id, UUID.class);
|
super(null);
|
||||||
}
|
|
||||||
|
|
||||||
public String region() {
|
|
||||||
return this.<String>get(supply::region, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mutable properties:
|
|
||||||
public String code() {
|
|
||||||
return this.<String>get(supply::code, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft code(String code) {
|
|
||||||
mutate(supply::code, code);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft setCode(String code) {
|
|
||||||
return code(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String description() {
|
|
||||||
return this.<String>get(supply::description, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft description(String description) {
|
|
||||||
mutate(supply::description, description);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft setDescription(String description) {
|
|
||||||
return description(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Long> demand() {
|
|
||||||
return this.<Map<String, Long>>get(supply::demand, Map.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft demand(Map<String, Long> demand) {
|
|
||||||
mutate(supply::demand, demand);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft setDemand(Map<String, Long> demand) {
|
|
||||||
return demand(demand);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> suppliers() {
|
|
||||||
return this.<List<String>>get(supply::suppliers, List.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft suppliers(List<String> suppliers) {
|
|
||||||
mutate(supply::suppliers, suppliers);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft setSuppliers(List<String> suppliers) {
|
|
||||||
return suppliers(suppliers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> shipments() {
|
|
||||||
return this.<Set<String>>get(supply::shipments, Set.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft shipments(Set<String> shipments) {
|
|
||||||
mutate(supply::shipments, shipments);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Draft setshipments(Set<String> shipments) {
|
|
||||||
return shipments(shipments);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Primary Key:
|
||||||
|
set(supply::id, UUIDs.timeBased());
|
||||||
|
set(supply::region, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draft(Supply supply) {
|
||||||
|
super((MapExportable) supply);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<Supply> getEntityClass() {
|
||||||
|
return Supply.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Immutable properties:
|
||||||
|
public UUID id() {
|
||||||
|
return this.<UUID>get(supply::id, UUID.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String region() {
|
||||||
|
return this.<String>get(supply::region, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable properties:
|
||||||
|
public String code() {
|
||||||
|
return this.<String>get(supply::code, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft code(String code) {
|
||||||
|
mutate(supply::code, code);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft setCode(String code) {
|
||||||
|
return code(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String description() {
|
||||||
|
return this.<String>get(supply::description, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft description(String description) {
|
||||||
|
mutate(supply::description, description);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft setDescription(String description) {
|
||||||
|
return description(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Long> demand() {
|
||||||
|
return this.<Map<String, Long>>get(supply::demand, Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft demand(Map<String, Long> demand) {
|
||||||
|
mutate(supply::demand, demand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft setDemand(Map<String, Long> demand) {
|
||||||
|
return demand(demand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> suppliers() {
|
||||||
|
return this.<List<String>>get(supply::suppliers, List.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft suppliers(List<String> suppliers) {
|
||||||
|
mutate(supply::suppliers, suppliers);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft setSuppliers(List<String> suppliers) {
|
||||||
|
return suppliers(suppliers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> shipments() {
|
||||||
|
return this.<Set<String>>get(supply::shipments, Set.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft shipments(Set<String> shipments) {
|
||||||
|
mutate(supply::shipments, shipments);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Draft setshipments(Set<String> shipments) {
|
||||||
|
return shipments(shipments);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,8 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
|
||||||
.value(cat::nickname, "garfield")
|
.value(cat::nickname, "garfield")
|
||||||
.value(cat::eatable, false)
|
.value(cat::eatable, false)
|
||||||
.sync();
|
.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());
|
Assert.assertTrue(animal.isPresent());
|
||||||
|
|
||||||
Cat cat = animal.get();
|
Cat cat = animal.get();
|
||||||
|
|
|
@ -20,6 +20,7 @@ import net.helenus.mapping.annotation.InheritedTable;
|
||||||
@InheritedTable
|
@InheritedTable
|
||||||
public interface Mammal extends Animal {
|
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 static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import java.util.*;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.Operator;
|
import net.helenus.core.Operator;
|
||||||
import net.helenus.core.operation.UpdateOperation;
|
import net.helenus.core.operation.UpdateOperation;
|
||||||
import net.helenus.core.reflect.Drafted;
|
|
||||||
import net.helenus.mapping.HelenusEntity;
|
|
||||||
import net.helenus.support.Fun;
|
import net.helenus.support.Fun;
|
||||||
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static User user;
|
static User user;
|
||||||
|
@ -102,11 +98,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
// select as object
|
// select as object
|
||||||
|
|
||||||
actual = session.<User>select(user)
|
actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
assertUsers(newUser, actual);
|
assertUsers(newUser, actual);
|
||||||
|
|
||||||
// select by columns
|
// select by columns
|
||||||
|
@ -192,11 +184,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
Assert.assertEquals("_albert", name);
|
Assert.assertEquals("_albert", name);
|
||||||
|
|
||||||
User u2 = session.<User>select(user)
|
User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
|
||||||
.where(user::id, eq(100L))
|
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(Long.valueOf(100L), u2.id());
|
Assert.assertEquals(Long.valueOf(100L), u2.id());
|
||||||
Assert.assertEquals("albert", u2.name());
|
Assert.assertEquals("albert", u2.name());
|
||||||
|
@ -204,31 +192,27 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
//
|
//
|
||||||
User greg =
|
User greg =
|
||||||
session
|
session
|
||||||
.<User>insert(user)
|
.<User>insert(user)
|
||||||
.value(user::name, "greg")
|
.value(user::name, "greg")
|
||||||
.value(user::age, 44)
|
.value(user::age, 44)
|
||||||
.value(user::type, UserType.USER)
|
.value(user::type, UserType.USER)
|
||||||
.value(user::id, 1234L)
|
.value(user::id, 1234L)
|
||||||
.sync();
|
.sync();
|
||||||
|
|
||||||
Optional<User> maybeGreg =
|
Optional<User> maybeGreg =
|
||||||
session
|
session.<User>select(user).where(user::id, eq(1234L)).single().sync();
|
||||||
.<User>select(user)
|
|
||||||
.where(user::id, eq(1234L))
|
|
||||||
.single()
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
|
|
||||||
session
|
session
|
||||||
.update()
|
.update()
|
||||||
.set(user::name, null)
|
.set(user::name, null)
|
||||||
.set(user::age, null)
|
.set(user::age, null)
|
||||||
.set(user::type, null)
|
.set(user::type, null)
|
||||||
.where(user::id, eq(100L))
|
.where(user::id, eq(100L))
|
||||||
.zipkinContext(null)
|
.zipkinContext(null)
|
||||||
.sync();
|
.sync();
|
||||||
|
|
||||||
Fun.Tuple3<String, Integer, UserType> tuple =
|
Fun.Tuple3<String, Integer, UserType> tuple =
|
||||||
session
|
session
|
||||||
|
@ -252,21 +236,16 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
public void testZipkin() throws Exception {
|
public void testZipkin() throws Exception {
|
||||||
session
|
session
|
||||||
.update()
|
.update()
|
||||||
.set(user::name, null)
|
.set(user::name, null)
|
||||||
.set(user::age, null)
|
.set(user::age, null)
|
||||||
.set(user::type, null)
|
.set(user::type, null)
|
||||||
.where(user::id, eq(100L))
|
.where(user::id, eq(100L))
|
||||||
.zipkinContext(null)
|
.zipkinContext(null)
|
||||||
.sync();
|
.sync();
|
||||||
|
|
||||||
|
|
||||||
UpdateOperation<ResultSet> update = session.update();
|
UpdateOperation<ResultSet> update = session.update();
|
||||||
update
|
update.set(user::name, null).zipkinContext(null).sync();
|
||||||
.set(user::name, null)
|
|
||||||
.zipkinContext(null)
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertUsers(User expected, User actual) {
|
private void assertUsers(User expected, User actual) {
|
||||||
|
|
|
@ -42,11 +42,8 @@ public class TupleMapTest extends TupleCollectionTest {
|
||||||
|
|
||||||
// read full object
|
// read full object
|
||||||
|
|
||||||
Book actual = session.<Book>select(book)
|
Book actual =
|
||||||
.where(book::id, Query.eq(id))
|
session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(writers, actual.writers());
|
assertEqualMaps(writers, actual.writers());
|
||||||
Assert.assertNull(actual.reviewers());
|
Assert.assertNull(actual.reviewers());
|
||||||
|
@ -77,11 +74,7 @@ public class TupleMapTest extends TupleCollectionTest {
|
||||||
|
|
||||||
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actual = session.<Book>select(book)
|
actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
|
||||||
.where(book::id, Query.eq(id))
|
|
||||||
.single()
|
|
||||||
.sync()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertEquals(id, actual.id());
|
Assert.assertEquals(id, actual.id());
|
||||||
assertEqualMaps(expected, actual.writers());
|
assertEqualMaps(expected, actual.writers());
|
||||||
|
@ -96,7 +89,8 @@ public class TupleMapTest extends TupleCollectionTest {
|
||||||
expected.put(third, unk);
|
expected.put(third, unk);
|
||||||
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
|
||||||
|
|
||||||
actualMap = 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);
|
assertEqualMaps(expected, actualMap);
|
||||||
|
|
||||||
// putAll operation
|
// putAll operation
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
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.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
import net.helenus.core.UnitOfWork;
|
import net.helenus.core.UnitOfWork;
|
||||||
|
@ -23,102 +26,125 @@ import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeTest() {
|
public static void beforeTest() {
|
||||||
session = Helenus.init(getSession())
|
session = Helenus.init(getSession()).showCql().autoCreateDrop().get();
|
||||||
.showCql()
|
}
|
||||||
.autoCreateDrop()
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAndThenOrdering() throws Exception {
|
public void testAndThenOrdering() throws Exception {
|
||||||
List<String> q = new ArrayList<String>(5);
|
List<String> q = new ArrayList<String>(5);
|
||||||
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
||||||
|
|
||||||
uow5 = session.begin();
|
uow5 = session.begin();
|
||||||
uow3 = session.begin(uow5);
|
uow3 = session.begin(uow5);
|
||||||
uow1 = session.begin(uow3);
|
uow1 = session.begin(uow3);
|
||||||
uow1.commit().andThen(() -> { q.add("1"); });
|
uow1.commit()
|
||||||
uow2 = session.begin(uow3);
|
.andThen(
|
||||||
uow2.commit().andThen(() -> { q.add("2"); });
|
() -> {
|
||||||
uow3.commit().andThen(() -> { q.add("3"); });
|
q.add("1");
|
||||||
uow4 = session.begin(uow5);
|
});
|
||||||
uow4.commit().andThen(() -> { q.add("4"); });
|
uow2 = session.begin(uow3);
|
||||||
uow5.commit().andThen(() -> { q.add("5"); });
|
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");
|
||||||
|
});
|
||||||
|
|
||||||
System.out.println(q);
|
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
|
||||||
|
public void testExceptionWithinAndThen() throws Exception {
|
||||||
|
List<String> q = new ArrayList<String>(5);
|
||||||
|
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
||||||
|
|
||||||
@Test
|
uow5 = session.begin();
|
||||||
public void testExceptionWithinAndThen() throws Exception {
|
uow4 = session.begin(uow5);
|
||||||
List<String> q = new ArrayList<String>(5);
|
try {
|
||||||
UnitOfWork uow1, uow2, uow3, uow4, uow5;
|
uow3 = session.begin(uow4);
|
||||||
|
uow1 = session.begin(uow3);
|
||||||
uow5 = session.begin();
|
uow1.commit()
|
||||||
uow4 = session.begin(uow5);
|
.andThen(
|
||||||
try {
|
() -> {
|
||||||
uow3 = session.begin(uow4);
|
|
||||||
uow1 = session.begin(uow3);
|
|
||||||
uow1.commit().andThen(() -> {
|
|
||||||
q.add("1");
|
q.add("1");
|
||||||
});
|
});
|
||||||
uow2 = session.begin(uow3);
|
uow2 = session.begin(uow3);
|
||||||
uow2.commit().andThen(() -> {
|
uow2.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
q.add("2");
|
q.add("2");
|
||||||
});
|
});
|
||||||
uow3.commit().andThen(() -> {
|
uow3.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
q.add("3");
|
q.add("3");
|
||||||
});
|
});
|
||||||
uow4.commit().andThen(() -> {
|
uow4.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
q.add("4");
|
q.add("4");
|
||||||
|
});
|
||||||
|
throw new Exception();
|
||||||
|
} catch (Exception e) {
|
||||||
|
uow4.abort();
|
||||||
|
}
|
||||||
|
uow5.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
|
q.add("5");
|
||||||
});
|
});
|
||||||
throw new Exception();
|
|
||||||
} catch(Exception e) {
|
|
||||||
uow4.abort();
|
|
||||||
}
|
|
||||||
uow5.commit().andThen(() -> { q.add("5"); });
|
|
||||||
|
|
||||||
System.out.println(q);
|
System.out.println(q);
|
||||||
Assert.assertTrue(q.isEmpty() == true);
|
Assert.assertTrue(q.isEmpty() == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClosableWillAbortWhenNotCommitted() throws Exception {
|
||||||
|
UnitOfWork unitOfWork;
|
||||||
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
unitOfWork = uow;
|
||||||
|
Assert.assertFalse(uow.hasAborted());
|
||||||
}
|
}
|
||||||
|
Assert.assertTrue(unitOfWork.hasAborted());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClosableWillAbortWhenNotCommitted() throws Exception {
|
public void testClosable() throws Exception {
|
||||||
UnitOfWork unitOfWork;
|
UnitOfWork unitOfWork;
|
||||||
try(UnitOfWork uow = session.begin()) {
|
try (UnitOfWork uow = session.begin()) {
|
||||||
unitOfWork = uow;
|
unitOfWork = uow;
|
||||||
Assert.assertFalse(uow.hasAborted());
|
Assert.assertFalse(uow.hasAborted());
|
||||||
}
|
uow.commit()
|
||||||
Assert.assertTrue(unitOfWork.hasAborted());
|
.andThen(
|
||||||
|
() -> {
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClosable() throws Exception {
|
|
||||||
UnitOfWork unitOfWork;
|
|
||||||
try(UnitOfWork uow = session.begin()) {
|
|
||||||
unitOfWork = uow;
|
|
||||||
Assert.assertFalse(uow.hasAborted());
|
|
||||||
uow.commit().andThen(() -> {
|
|
||||||
Assert.assertFalse(uow.hasAborted());
|
Assert.assertFalse(uow.hasAborted());
|
||||||
Assert.assertTrue(uow.hasCommitted());
|
Assert.assertTrue(uow.hasCommitted());
|
||||||
});
|
});
|
||||||
}
|
|
||||||
Assert.assertFalse(unitOfWork.hasAborted());
|
|
||||||
Assert.assertTrue(unitOfWork.hasCommitted());
|
|
||||||
}
|
}
|
||||||
|
Assert.assertFalse(unitOfWork.hasAborted());
|
||||||
|
Assert.assertTrue(unitOfWork.hasCommitted());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.*;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType.Name;
|
import com.datastax.driver.core.DataType.Name;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
@UDT
|
@UDT
|
||||||
public interface Directory extends FilesystemNode {
|
public interface Directory extends FilesystemNode {
|
||||||
|
|
||||||
@Types.Set(Name.TIMEUUID)
|
@Types.Set(Name.TIMEUUID)
|
||||||
Set<FilesystemNode> inodes();
|
Set<FilesystemNode> inodes();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,9 @@ package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
|
|
||||||
@UDT
|
@UDT
|
||||||
public interface File extends FilesystemNode {
|
public interface File extends FilesystemNode {
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
byte[] data();
|
byte[] data();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,5 @@ import net.helenus.mapping.annotation.UDT;
|
||||||
@UDT
|
@UDT
|
||||||
public interface FileAttributes {
|
public interface FileAttributes {
|
||||||
|
|
||||||
String owner();
|
String owner();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.*;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
@Table("fs")
|
@Table("fs")
|
||||||
public interface FilesystemNode {
|
public interface FilesystemNode {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID inode();
|
UUID inode();
|
||||||
|
|
||||||
@ClusteringColumn
|
@ClusteringColumn
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
@Column
|
|
||||||
FileAttributes attr();
|
|
||||||
|
|
||||||
|
@Column
|
||||||
|
FileAttributes attr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.unitofwork;
|
package net.helenus.test.integration.core.unitofwork;
|
||||||
|
|
||||||
|
import static net.helenus.core.Query.eq;
|
||||||
|
|
||||||
import com.datastax.driver.core.utils.UUIDs;
|
import com.datastax.driver.core.utils.UUIDs;
|
||||||
|
import java.util.UUID;
|
||||||
import net.bytebuddy.utility.RandomString;
|
import net.bytebuddy.utility.RandomString;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.HelenusSession;
|
import net.helenus.core.HelenusSession;
|
||||||
|
@ -29,167 +32,161 @@ import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static net.helenus.core.Query.eq;
|
|
||||||
|
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
@Cacheable
|
@Cacheable
|
||||||
interface Widget {
|
interface Widget {
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
UUID id();
|
UUID id();
|
||||||
@Column
|
|
||||||
String name();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Column
|
||||||
|
String name();
|
||||||
|
}
|
||||||
|
|
||||||
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
|
||||||
|
|
||||||
static Widget widget;
|
static Widget widget;
|
||||||
static HelenusSession session;
|
static HelenusSession session;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeTest() {
|
||||||
|
session = Helenus.init(getSession()).showCql().add(Widget.class).autoCreateDrop().get();
|
||||||
|
widget = session.dsl(Widget.class);
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@Test
|
||||||
public static void beforeTest() {
|
public void testSelectAfterSelect() throws Exception {
|
||||||
session = Helenus.init(getSession())
|
Widget w1, w2;
|
||||||
.showCql()
|
UUID key = UUIDs.timeBased();
|
||||||
.add(Widget.class)
|
|
||||||
.autoCreateDrop()
|
|
||||||
.get();
|
|
||||||
widget = session.dsl(Widget.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
// This should inserted Widget, but not cache it.
|
||||||
public void testSelectAfterSelect() throws Exception {
|
session
|
||||||
Widget w1, w2;
|
.<Widget>insert(widget)
|
||||||
UUID key = UUIDs.timeBased();
|
.value(widget::id, key)
|
||||||
|
.value(widget::name, RandomString.make(20))
|
||||||
|
.sync();
|
||||||
|
|
||||||
// This should inserted Widget, but not cache it.
|
try (UnitOfWork uow = session.begin()) {
|
||||||
session.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
try (UnitOfWork uow = session.begin()) {
|
// This should read from the database and return a Widget.
|
||||||
|
w1 =
|
||||||
|
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||||
|
|
||||||
// This should read from the database and return a Widget.
|
// This should read from the cache and get the same instance of a Widget.
|
||||||
w1 = session.<Widget>select(widget)
|
w2 =
|
||||||
.where(widget::id, eq(key))
|
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
|
||||||
.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);
|
|
||||||
|
|
||||||
uow.commit()
|
|
||||||
.andThen(() -> {
|
|
||||||
Assert.assertEquals(w1, w2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSelectAfterNestedSelect() throws Exception {
|
|
||||||
Widget w1, w2, w3, w4;
|
|
||||||
UUID key1 = UUIDs.timeBased();
|
|
||||||
UUID key2 = UUIDs.timeBased();
|
|
||||||
|
|
||||||
// This should inserted Widget, and not cache it in uow1.
|
|
||||||
try (UnitOfWork uow1 = session.begin()) {
|
|
||||||
w1 = session.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key1)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync(uow1);
|
|
||||||
|
|
||||||
try (UnitOfWork uow2 = session.begin(uow1)) {
|
|
||||||
|
|
||||||
// This should read from uow1's cache and return the same Widget.
|
|
||||||
w2 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key1))
|
|
||||||
.single()
|
|
||||||
.sync(uow2)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
|
uow.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
Assert.assertEquals(w1, w2);
|
Assert.assertEquals(w1, w2);
|
||||||
|
});
|
||||||
w3 = session.<Widget>insert(widget)
|
|
||||||
.value(widget::id, key2)
|
|
||||||
.value(widget::name, RandomString.make(20))
|
|
||||||
.sync(uow2);
|
|
||||||
|
|
||||||
uow2.commit()
|
|
||||||
.andThen(() -> {
|
|
||||||
Assert.assertEquals(w1, w2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
|
||||||
w4 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key2))
|
|
||||||
.single()
|
|
||||||
.sync(uow1)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
uow1.commit()
|
|
||||||
.andThen(() -> {
|
|
||||||
Assert.assertEquals(w3, w4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
}
|
||||||
@Test
|
|
||||||
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
|
|
||||||
Widget w1, w2, w3, w4;
|
|
||||||
UUID key = UUIDs.timeBased();
|
|
||||||
|
|
||||||
try (UnitOfWork uow = session.begin()) {
|
@Test
|
||||||
|
public void testSelectAfterNestedSelect() throws Exception {
|
||||||
|
Widget w1, w2, w3, w4;
|
||||||
|
UUID key1 = UUIDs.timeBased();
|
||||||
|
UUID key2 = UUIDs.timeBased();
|
||||||
|
|
||||||
// This should cache the inserted Widget.
|
// This should inserted Widget, and not cache it in uow1.
|
||||||
w1 = session.<Widget>insert(widget)
|
try (UnitOfWork uow1 = session.begin()) {
|
||||||
.value(widget::id, key)
|
w1 =
|
||||||
.value(widget::name, RandomString.make(20))
|
session
|
||||||
.sync(uow);
|
.<Widget>insert(widget)
|
||||||
|
.value(widget::id, key1)
|
||||||
|
.value(widget::name, RandomString.make(20))
|
||||||
|
.sync(uow1);
|
||||||
|
|
||||||
// This should read from the cache and get the same instance of a Widget.
|
try (UnitOfWork uow2 = session.begin(uow1)) {
|
||||||
w2 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key))
|
|
||||||
.single()
|
|
||||||
.sync(uow)
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
uow.commit()
|
// This should read from uow1's cache and return the same Widget.
|
||||||
.andThen(() -> {
|
w2 =
|
||||||
Assert.assertEquals(w1, w2);
|
session
|
||||||
});
|
.<Widget>select(widget)
|
||||||
}
|
.where(widget::id, eq(key1))
|
||||||
|
|
||||||
// This should read the widget from the session cache and maintain object identity.
|
|
||||||
w3 = session.<Widget>select(widget)
|
|
||||||
.where(widget::id, eq(key))
|
|
||||||
.single()
|
.single()
|
||||||
.sync()
|
.sync(uow2)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
Assert.assertEquals(w1, w3);
|
Assert.assertEquals(w1, w2);
|
||||||
|
|
||||||
// This should read the widget from the database, no object identity but values should match.
|
w3 =
|
||||||
w4 = session.<Widget>select(widget)
|
session
|
||||||
.where(widget::id, eq(key))
|
.<Widget>insert(widget)
|
||||||
.ignoreCache()
|
.value(widget::id, key2)
|
||||||
.single()
|
.value(widget::name, RandomString.make(20))
|
||||||
.sync()
|
.sync(uow2);
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
Assert.assertNotEquals(w1, w4);
|
uow2.commit()
|
||||||
Assert.assertTrue(w1.equals(w4));
|
.andThen(
|
||||||
|
() -> {
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should read from the cache and get the same instance of a Widget.
|
||||||
|
w4 =
|
||||||
|
session
|
||||||
|
.<Widget>select(widget)
|
||||||
|
.where(widget::id, eq(key2))
|
||||||
|
.single()
|
||||||
|
.sync(uow1)
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
uow1.commit()
|
||||||
|
.andThen(
|
||||||
|
() -> {
|
||||||
|
Assert.assertEquals(w3, w4);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
/*
|
||||||
|
@Test
|
||||||
|
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
|
||||||
|
Widget w1, w2, w3, w4;
|
||||||
|
UUID key = UUIDs.timeBased();
|
||||||
|
|
||||||
|
try (UnitOfWork uow = session.begin()) {
|
||||||
|
|
||||||
|
// This should cache the inserted Widget.
|
||||||
|
w1 = session.<Widget>insert(widget)
|
||||||
|
.value(widget::id, key)
|
||||||
|
.value(widget::name, RandomString.make(20))
|
||||||
|
.sync(uow);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
uow.commit()
|
||||||
|
.andThen(() -> {
|
||||||
|
Assert.assertEquals(w1, w2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should read the widget from the session cache and maintain object identity.
|
||||||
|
w3 = session.<Widget>select(widget)
|
||||||
|
.where(widget::id, eq(key))
|
||||||
|
.single()
|
||||||
|
.sync()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Assert.assertEquals(w1, w3);
|
||||||
|
|
||||||
|
// This should read the widget from the database, no object identity but values should match.
|
||||||
|
w4 = session.<Widget>select(widget)
|
||||||
|
.where(widget::id, eq(key))
|
||||||
|
.ignoreCache()
|
||||||
|
.single()
|
||||||
|
.sync()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
Assert.assertNotEquals(w1, w4);
|
||||||
|
Assert.assertTrue(w1.equals(w4));
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import net.helenus.core.reflect.Drafted;
|
import net.helenus.core.reflect.Drafted;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
|
||||||
import net.helenus.mapping.annotation.*;
|
import net.helenus.mapping.annotation.*;
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
|
|
Loading…
Reference in a new issue