use of io.requery.meta.Attribute in project requery by requery.
the class EntityWriter method batchInsert.
GeneratedKeys<E> batchInsert(Iterable<E> entities, boolean returnKeys) {
// true if using JDBC batching
final boolean batchInStatement = canBatchInStatement();
final int batchSize = context.getBatchUpdateSize();
final EntityReader<E, S> reader = context.read(entityClass);
final Iterator<E> iterator = entities.iterator();
final boolean isImmtuable = type.isImmutable();
final GeneratedKeys<E> keys = returnKeys && hasGeneratedKey ? new GeneratedKeys<E>() : null;
int collectionSize = entities instanceof Collection ? ((Collection) entities).size() : -1;
@SuppressWarnings("unchecked") final E[] elements = (E[]) new Object[Math.min(collectionSize, batchSize)];
while (iterator.hasNext()) {
int index = 0;
Map<Class<? extends S>, List<S>> associations = new HashMap<>();
while (iterator.hasNext() && index < batchSize) {
E entity = iterator.next();
EntityProxy<E> proxy = proxyProvider.apply(entity);
elements[index] = entity;
if (hasForeignKeys) {
for (Attribute<E, ?> attribute : associativeAttributes) {
S referenced = foreignKeyReference(proxy, attribute);
if (referenced != null) {
EntityProxy<S> otherProxy = context.proxyOf(referenced, false);
if (otherProxy != null && !otherProxy.isLinked()) {
Class<? extends S> key = otherProxy.type().getClassType();
List<S> values = associations.get(key);
if (values == null) {
associations.put(key, values = new ArrayList<>());
}
values.add(referenced);
}
}
}
}
incrementVersion(proxy);
context.getStateListener().preInsert(entity, proxy);
index++;
}
cascadeBatch(associations);
final int count = index;
GeneratedResultReader keyReader = null;
if (hasGeneratedKey) {
keyReader = new GeneratedResultReader() {
@Override
public void read(int index, ResultSet results) throws SQLException {
// check if reading batch keys, otherwise read 1
int readCount = batchInStatement ? count : 1;
for (int i = index; i < index + readCount; i++) {
if (!results.next()) {
throw new IllegalStateException();
}
EntityProxy<E> proxy = proxyProvider.apply(elements[i]);
Settable<E> keyProxy = keys == null ? proxy : keys.proxy(isImmtuable ? null : proxy);
readGeneratedKeys(keyProxy, results);
}
}
@Override
public String[] generatedColumns() {
return generatedColumnNames;
}
};
}
BatchUpdateOperation<E> operation = new BatchUpdateOperation<>(context, elements, count, this, keyReader, batchInStatement);
QueryElement<int[]> query = new QueryElement<>(QueryType.INSERT, model, operation);
query.from(entityClass);
for (Attribute attribute : bindableAttributes) {
query.value((Expression) attribute, null);
}
int[] updates = query.get();
for (int i = 0; i < updates.length; i++) {
E entity = elements[i];
EntityProxy<E> proxy = proxyProvider.apply(entity);
checkRowsAffected(updates[i], entity, proxy);
proxy.link(reader);
updateAssociations(Cascade.AUTO, entity, proxy, null);
context.getStateListener().postInsert(entity, proxy);
// cache entity
if (cacheable) {
cache.put(entityClass, proxy.key(), entity);
}
}
}
return keys;
}
use of io.requery.meta.Attribute in project requery by requery.
the class EntityReader method fromResult.
final E fromResult(E entity, ResultSet results, Attribute[] selection) throws SQLException {
// if refreshing (entity not null) overwrite the properties
boolean overwrite = entity != null || stateless;
if (entity == null) {
// get or create the entity object
if (cacheable) {
synchronized (type) {
// try lookup cached object
final Object key = readCacheKey(results);
if (key != null) {
entity = cache.get(type.getClassType(), key);
}
// not cached create a new one
if (entity == null) {
entity = createEntity();
if (key != null) {
cache.put(type.getClassType(), key, entity);
}
}
}
} else {
entity = createEntity();
}
}
// set the properties
EntityProxy<E> proxy = type.getProxyProvider().apply(entity);
synchronized (proxy.syncObject()) {
proxy.link(this);
int index = 1;
for (Attribute expression : selection) {
@SuppressWarnings("unchecked") Attribute<E, ?> attribute = (Attribute<E, ?>) expression;
boolean isAssociation = attribute.isAssociation();
if ((attribute.isForeignKey() || attribute.isKey()) && isAssociation) {
// handle loading the foreign key into referenced object
Attribute referenced = Attributes.get(attribute.getReferencedAttribute());
Object key = mapping.read((Expression) referenced, results, index);
if (key != null) {
Object value = proxy.get(attribute, false);
if (value == null) {
// create one...
Class classType = attribute.getClassType();
EntityReader reader = context.read(classType);
value = reader.createEntity();
}
context.proxyOf(value, false).set(Attributes.get(attribute.getReferencedAttribute()), key, PropertyState.LOADED);
// leave in fetch state if only key is loaded
PropertyState state = PropertyState.LOADED;
if (!stateless) {
state = proxy.getState(attribute);
state = state == PropertyState.LOADED ? state : PropertyState.FETCH;
}
proxy.setObject(attribute, value, state);
}
} else if (isAssociation) {
continue;
} else if (overwrite || proxy.getState(attribute) != PropertyState.MODIFIED) {
if (attribute.getPrimitiveKind() != null) {
readPrimitiveField(proxy, attribute, results, index);
} else {
Object value = mapping.read((Expression) attribute, results, index);
proxy.setObject(attribute, value, PropertyState.LOADED);
}
}
index++;
}
}
context.getStateListener().postLoad(entity, proxy);
return entity;
}
use of io.requery.meta.Attribute in project requery by requery.
the class EntityReader method refresh.
private E refresh(E entity, EntityProxy<E> proxy, final Set<Attribute<E, ?>> attributes) {
Predicate<Attribute<E, ?>> basicFilter = new Predicate<Attribute<E, ?>>() {
@Override
public boolean test(Attribute<E, ?> value) {
return attributes.contains(value) && (!value.isAssociation() || value.isForeignKey());
}
};
FilteringIterator<Attribute<E, ?>> filterator = new FilteringIterator<>(attributes.iterator(), basicFilter);
if (filterator.hasNext()) {
QueryBuilder qb = new QueryBuilder(context.getQueryBuilderOptions()).keyword(SELECT).commaSeparated(filterator, new QueryBuilder.Appender<Attribute<E, ?>>() {
@Override
public void append(QueryBuilder qb, Attribute<E, ?> value) {
String versionColumn = context.getPlatform().versionColumnDefinition().columnName();
if (value.isVersion() && versionColumn != null) {
qb.append(versionColumn).space().append(AS).space().append(value.getName()).space();
} else {
qb.attribute(value);
}
}
}).keyword(FROM).tableName(type.getName()).keyword(WHERE).appendWhereConditions(type.getKeyAttributes());
String sql = qb.toString();
try (Connection connection = context.getConnection();
PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
for (Attribute<E, ?> attribute : type.getKeyAttributes()) {
Object value = proxy.getKey(attribute);
if (value == null) {
throw new MissingKeyException(proxy);
}
mapping.write((Expression) attribute, statement, index++, value);
}
context.getStatementListener().beforeExecuteQuery(statement, sql, null);
ResultSet results = statement.executeQuery();
context.getStatementListener().afterExecuteQuery(statement);
if (results.next()) {
Attribute[] selection = new Attribute[attributes.size()];
attributes.toArray(selection);
// modify the given entity
if (type.isImmutable()) {
entity = fromBuilder(results, selection);
} else {
entity = fromResult(entity, results, selection);
}
}
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
// refresh associations
for (Attribute<E, ?> attribute : attributes) {
// if it's a foreign key its resolved as part of the basic properties
if (attribute.isAssociation()) {
refreshAssociation(proxy, attribute);
}
}
return entity;
}
use of io.requery.meta.Attribute 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.Attribute in project requery by requery.
the class QueryBuilder method tableNames.
public QueryBuilder tableNames(Iterable<Expression<?>> values) {
Set<Type<?>> types = new LinkedHashSet<>();
for (Expression<?> expression : values) {
if (expression.getExpressionType() == ExpressionType.ATTRIBUTE) {
Attribute attribute = (Attribute) expression;
types.add(attribute.getDeclaringType());
}
}
return commaSeparated(types, new Appender<Type<?>>() {
@Override
public void append(QueryBuilder qb, Type<?> value) {
tableName(value.getName());
}
});
}
Aggregations