use of io.requery.meta.QueryAttribute in project requery by requery.
the class DefaultOutput method appendConditionValue.
private void appendConditionValue(Expression expression, Object value, boolean parameterize) {
if (value instanceof QueryAttribute) {
appendColumn((Expression<?>) value);
} else if (value instanceof Supplier && ((Supplier) value).get() instanceof QueryAttribute) {
appendColumn((Expression<?>) ((Supplier) value).get());
} else if (value instanceof NamedExpression) {
NamedExpression namedExpression = (NamedExpression) value;
qb.append(namedExpression.getName());
} else if (value instanceof Function) {
appendFunction((Function) value);
} else if (value instanceof Collection && expression.getExpressionType() == ExpressionType.ROW) {
qb.openParenthesis();
qb.commaSeparated((Collection) value);
qb.closeParenthesis();
} else {
if (parameterize) {
if (parameters != null) {
parameters.add(expression, value);
}
qb.append("?").space();
} else {
if (value instanceof CharSequence) {
qb.appendQuoted(value.toString()).space();
} else {
qb.append(value).space();
}
}
}
}
use of io.requery.meta.QueryAttribute in project requery by requery.
the class EntityWriter method updateAssociation.
@SuppressWarnings("unchecked")
private void updateAssociation(Cascade mode, E entity, EntityProxy<E> proxy, Attribute<E, ?> attribute) {
switch(attribute.getCardinality()) {
case ONE_TO_ONE:
S value = (S) proxy.get(attribute, false);
if (value != null) {
Attribute<S, Object> mapped = Attributes.get(attribute.getMappedAttribute());
EntityProxy<S> referred = context.proxyOf(value, true);
referred.set(mapped, entity, PropertyState.MODIFIED);
cascadeWrite(mode, value, referred);
} else if (!stateless) {
throw new PersistenceException("1-1 relationship can only be removed from the owning side");
}
break;
case ONE_TO_MANY:
Object relation = proxy.get(attribute, false);
if (relation instanceof ObservableCollection) {
ObservableCollection<S> collection = (ObservableCollection<S>) relation;
CollectionChanges<?, S> changes = (CollectionChanges<?, S>) collection.observer();
List<S> added = new ArrayList<>(changes.addedElements());
List<S> removed = new ArrayList<>(changes.removedElements());
changes.clear();
for (S element : added) {
updateMappedAssociation(mode, element, attribute, entity);
}
for (S element : removed) {
updateMappedAssociation(Cascade.UPDATE, element, attribute, null);
}
} else if (relation instanceof Iterable) {
Iterable<S> iterable = (Iterable<S>) relation;
for (S added : iterable) {
updateMappedAssociation(mode, added, attribute, entity);
}
} else {
throw new IllegalStateException("unsupported relation type " + relation);
}
break;
case MANY_TO_MANY:
final Class referencedClass = attribute.getReferencedClass();
if (referencedClass == null) {
throw new IllegalStateException("Invalid referenced class in " + attribute);
}
Type<?> referencedType = model.typeOf(referencedClass);
QueryAttribute<S, Object> tKey = null;
QueryAttribute<S, Object> uKey = null;
for (Attribute a : referencedType.getAttributes()) {
Class<?> referenced = a.getReferencedClass();
if (referenced != null) {
if (tKey == null && entityClass.isAssignableFrom(referenced)) {
tKey = Attributes.query(a);
} else if (attribute.getElementClass() != null && attribute.getElementClass().isAssignableFrom(referenced)) {
uKey = Attributes.query(a);
}
}
}
Objects.requireNotNull(tKey);
Objects.requireNotNull(uKey);
Attribute<E, Object> tRef = Attributes.get(tKey.getReferencedAttribute());
Attribute<S, Object> uRef = Attributes.get(uKey.getReferencedAttribute());
CollectionChanges<?, S> changes = null;
relation = proxy.get(attribute, false);
Iterable<S> addedElements = (Iterable<S>) relation;
boolean isObservable = relation instanceof ObservableCollection;
if (relation instanceof ObservableCollection) {
ObservableCollection<S> collection = (ObservableCollection<S>) relation;
changes = (CollectionChanges<?, S>) collection.observer();
if (changes != null) {
addedElements = changes.addedElements();
}
}
for (S added : addedElements) {
S junction = (S) referencedType.getFactory().get();
EntityProxy<S> junctionProxy = context.proxyOf(junction, false);
EntityProxy<S> uProxy = context.proxyOf(added, false);
if (attribute.getCascadeActions().contains(CascadeAction.SAVE)) {
cascadeWrite(mode, added, uProxy);
}
Object tValue = proxy.get(tRef, false);
Object uValue = uProxy.get(uRef, false);
junctionProxy.set(tKey, tValue, PropertyState.MODIFIED);
junctionProxy.set(uKey, uValue, PropertyState.MODIFIED);
Cascade cascade = isObservable && mode == Cascade.UPSERT ? Cascade.UPSERT : Cascade.INSERT;
cascadeWrite(cascade, junction, null);
}
if (changes != null) {
Object keyValue = proxy.get(tRef, false);
for (S removed : changes.removedElements()) {
Object otherValue = context.proxyOf(removed, false).get(uRef);
Class<? extends S> removeType = (Class<? extends S>) referencedType.getClassType();
Supplier<? extends Scalar<Integer>> query = queryable.delete(removeType).where(tKey.equal(keyValue)).and(uKey.equal(otherValue));
int count = query.get().value();
if (count != 1) {
throw new RowCountException(1, count);
}
}
changes.clear();
}
break;
case MANY_TO_ONE:
default:
break;
}
context.read(type.getClassType()).refresh(entity, proxy, attribute);
}
use of io.requery.meta.QueryAttribute in project requery by requery.
the class EntityReader method batchRefresh.
@SafeVarargs
final Iterable<E> batchRefresh(Iterable<E> entities, Attribute<E, ?>... attributes) {
// if the type is immutable return a new collection with the rebuilt objects
final Collection<E> collection = type.isImmutable() ? new ArrayList<E>() : null;
if (keyAttribute == null) {
// non optimal case objects with multiple keys or no keys
for (E entity : entities) {
entity = refresh(entity, type.getProxyProvider().apply(entity), attributes);
if (collection != null) {
collection.add(entity);
}
}
} else {
Set<Expression<?>> selection = new LinkedHashSet<>();
Attribute[] selectAttributes;
if (attributes == null || attributes.length == 0) {
selection = defaultSelection;
selectAttributes = defaultSelectionAttributes;
} else {
LinkedHashSet<Attribute> selectedAttributes = new LinkedHashSet<>();
selection.add(keyAttribute);
selectedAttributes.add(keyAttribute);
for (Attribute<E, ?> attribute : attributes) {
if (attribute.isVersion()) {
selection.add(aliasVersion(attribute));
} else if (!attribute.isAssociation()) {
QueryAttribute<E, ?> queryAttribute = Attributes.query(attribute);
selection.add(queryAttribute);
}
selectedAttributes.add(attribute);
}
selectAttributes = selectedAttributes.toArray(new Attribute[selection.size()]);
}
Map<Object, EntityProxy<E>> map = new HashMap<>();
for (E entity : entities) {
EntityProxy<E> proxy = type.getProxyProvider().apply(entity);
Object key = proxy.key();
if (key == null) {
throw new MissingKeyException();
}
map.put(key, proxy);
}
Condition<?, ?> condition = Attributes.query(keyAttribute).in(map.keySet());
if (type.isCacheable()) {
final Consumer<E> collector = new Consumer<E>() {
@Override
public void accept(E e) {
if (collection != null) {
collection.add(e);
}
}
};
// readResult will merge the results into the target object in cache mode
ResultReader<E> resultReader = newResultReader(selectAttributes);
SelectOperation<E> select = new SelectOperation<>(context, resultReader);
QueryElement<? extends Result<E>> query = new QueryElement<>(QueryType.SELECT, context.getModel(), select);
try (Result<E> result = query.select(selection).where(condition).get()) {
result.each(collector);
}
} else {
try (Result<Tuple> result = queryable.select(selection).where(condition).get()) {
for (Tuple tuple : result) {
Object key = tuple.get((Expression) keyAttribute);
EntityProxy<E> proxy = map.get(key);
synchronized (proxy.syncObject()) {
for (Expression expression : selection) {
Object value = tuple.get(expression);
if (expression instanceof AliasedExpression) {
AliasedExpression aliased = (AliasedExpression) expression;
expression = aliased.getInnerExpression();
}
Attribute<E, Object> attribute = Attributes.query((Attribute) expression);
proxy.set(attribute, value, PropertyState.LOADED);
}
}
}
}
}
// associations TODO can be optimized
if (attributes != null) {
for (Attribute<E, ?> attribute : attributes) {
if (attribute.isAssociation()) {
for (EntityProxy<E> proxy : map.values()) {
refreshAssociation(proxy, attribute);
}
}
}
}
}
return collection == null ? entities : collection;
}
use of io.requery.meta.QueryAttribute in project requery by requery.
the class EntityDataStore method findByKey.
@Override
public <E extends T, K> E findByKey(Class<E> type, K key) {
Type<E> entityType = entityModel.typeOf(type);
if (entityType.isCacheable() && entityCache != null) {
E entity = entityCache.get(type, key);
if (entity != null) {
return entity;
}
}
Set<Attribute<E, ?>> keys = entityType.getKeyAttributes();
if (keys.isEmpty()) {
throw new MissingKeyException();
}
Selection<? extends Result<E>> selection = select(type);
if (keys.size() == 1) {
QueryAttribute<E, Object> attribute = Attributes.query(keys.iterator().next());
selection.where(attribute.equal(key));
} else {
if (key instanceof CompositeKey) {
CompositeKey compositeKey = (CompositeKey) key;
for (Attribute<E, ?> attribute : keys) {
QueryAttribute<E, Object> keyAttribute = Attributes.query(attribute);
Object value = compositeKey.get(keyAttribute);
selection.where(keyAttribute.equal(value));
}
} else {
throw new IllegalArgumentException("CompositeKey required");
}
}
return selection.get().firstOrNull();
}
Aggregations