Search in sources :

Example 1 with QueryElement

use of io.requery.query.element.QueryElement 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;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) WHERE(io.requery.sql.Keyword.WHERE) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) QueryElement(io.requery.query.element.QueryElement) AliasedExpression(io.requery.query.AliasedExpression) EntityProxy(io.requery.proxy.EntityProxy) Consumer(io.requery.util.function.Consumer) AliasedExpression(io.requery.query.AliasedExpression) Expression(io.requery.query.Expression) QueryAttribute(io.requery.meta.QueryAttribute) Tuple(io.requery.query.Tuple)

Example 2 with QueryElement

use of io.requery.query.element.QueryElement in project requery by requery.

the class EntityWriter method insert.

void insert(final E entity, EntityProxy<E> proxy, Cascade mode, GeneratedKeys<E> keys) {
    // if the type is immutable return the key(s) to the caller instead of modifying the object
    GeneratedResultReader keyReader = null;
    if (hasGeneratedKey) {
        final Settable<E> settable = keys == null ? proxy : keys;
        keyReader = new GeneratedResultReader() {

            @Override
            public void read(int index, ResultSet results) throws SQLException {
                if (results.next()) {
                    readGeneratedKeys(settable, results);
                }
            }

            @Override
            public String[] generatedColumns() {
                return generatedColumnNames;
            }
        };
    }
    EntityUpdateOperation insert = new EntityUpdateOperation(context, keyReader) {

        @Override
        public int bindParameters(PreparedStatement statement) throws SQLException {
            return EntityWriter.this.bindParameters(statement, entity, null);
        }
    };
    QueryElement<Scalar<Integer>> query = new QueryElement<>(QueryType.INSERT, model, insert);
    query.from(entityClass);
    for (Attribute<E, ?> attribute : associativeAttributes) {
        // persist the foreign key object if needed
        cascadeKeyReference(Cascade.INSERT, proxy, attribute);
    }
    incrementVersion(proxy);
    for (Attribute attribute : bindableAttributes) {
        query.value((Expression) attribute, null);
    }
    context.getStateListener().preInsert(entity, proxy);
    checkRowsAffected(query.get().value(), entity, null);
    proxy.link(context.read(entityClass));
    updateAssociations(mode, entity, proxy, null);
    context.getStateListener().postInsert(entity, proxy);
    // cache entity
    if (cacheable) {
        cache.put(entityClass, proxy.key(), entity);
    }
}
Also used : UPDATE(io.requery.query.element.QueryType.UPDATE) SQLException(java.sql.SQLException) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) PreparedStatement(java.sql.PreparedStatement) QueryElement(io.requery.query.element.QueryElement) Scalar(io.requery.query.Scalar) ResultSet(java.sql.ResultSet)

Example 3 with QueryElement

use of io.requery.query.element.QueryElement 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;
}
Also used : UPDATE(io.requery.query.element.QueryType.UPDATE) HashMap(java.util.HashMap) SQLException(java.sql.SQLException) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) ArrayList(java.util.ArrayList) QueryElement(io.requery.query.element.QueryElement) EntityProxy(io.requery.proxy.EntityProxy) Settable(io.requery.proxy.Settable) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ObservableCollection(io.requery.util.ObservableCollection) Collection(java.util.Collection)

Aggregations

Attribute (io.requery.meta.Attribute)3 QueryAttribute (io.requery.meta.QueryAttribute)3 QueryElement (io.requery.query.element.QueryElement)3 EntityProxy (io.requery.proxy.EntityProxy)2 UPDATE (io.requery.query.element.QueryType.UPDATE)2 ResultSet (java.sql.ResultSet)2 SQLException (java.sql.SQLException)2 HashMap (java.util.HashMap)2 Settable (io.requery.proxy.Settable)1 AliasedExpression (io.requery.query.AliasedExpression)1 Expression (io.requery.query.Expression)1 Scalar (io.requery.query.Scalar)1 Tuple (io.requery.query.Tuple)1 WHERE (io.requery.sql.Keyword.WHERE)1 ObservableCollection (io.requery.util.ObservableCollection)1 Consumer (io.requery.util.function.Consumer)1 PreparedStatement (java.sql.PreparedStatement)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 LinkedHashMap (java.util.LinkedHashMap)1