Search in sources :

Example 1 with EntityProxy

use of io.requery.proxy.EntityProxy 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)

Example 2 with EntityProxy

use of io.requery.proxy.EntityProxy 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)

Aggregations

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