Search in sources :

Example 26 with QualifiedName

use of org.qi4j.api.common.QualifiedName in project qi4j-sdk by Qi4j.

the class AbstractSQLIndexing method indexEntities.

@Override
public void indexEntities(Iterable<EntityState> changedStates) throws SQLException {
    final String schemaName = this._state.schemaName().get();
    final SQLVendor vendor = this.descriptor.metaInfo(SQLVendor.class);
    Connection connectionTest = AbstractSQLStartup.CONNECTION_FOR_REINDEXING.get();
    boolean connectionFromStartupWasNull = connectionTest == null;
    boolean wasAutoCommit = false;
    boolean wasReadOnly = false;
    if (connectionFromStartupWasNull) {
        connectionTest = this._dataSource.getConnection();
    } else {
        wasAutoCommit = connectionTest.getAutoCommit();
        wasReadOnly = connectionTest.isReadOnly();
    }
    final Connection connection = connectionTest;
    PreparedStatement updateEntityTablePS = null;
    PreparedStatement removeEntityPS = null;
    PreparedStatement insertToPropertyQNamesPS = null;
    PreparedStatement clearEntityDataPS = null;
    Lazy<PreparedStatement, SQLException> queryEntityPKPS = new Lazy<>(new LazyInit<PreparedStatement, SQLException>() {

        @Override
        public PreparedStatement create() throws SQLException {
            return connection.prepareStatement(vendor.toString(createQueryEntityPkByIdentityStatement(schemaName, vendor)));
        }
    });
    Lazy<PreparedStatement, SQLException> insertToEntityTableAutoGenerated = new Lazy<>(new LazyInit<PreparedStatement, SQLException>() {

        @Override
        public PreparedStatement create() throws SQLException {
            return connection.prepareStatement(createInsertStatementWithAutoGeneratedIDForEntitiesTable(schemaName, ENTITY_TABLE_NAME, vendor).toString());
        }
    });
    Lazy<PreparedStatement, SQLException> insertToEntityTypeTablePS = new Lazy<>(new LazyInit<PreparedStatement, SQLException>() {

        @Override
        public PreparedStatement create() throws SQLException {
            return connection.prepareStatement(createInsertEntityTypeStatement(schemaName, vendor).toString());
        }
    });
    Map<QualifiedName, PreparedStatement> qNameInsertPSs = new HashMap<>();
    try {
        connection.setAutoCommit(false);
        connection.setReadOnly(false);
        // TODO cache all queries.
        updateEntityTablePS = connection.prepareStatement(this.createUpdateEntityTableStatement(schemaName, vendor).toString());
        removeEntityPS = connection.prepareStatement(this.createDeleteFromEntityTableStatement(schemaName, vendor).toString());
        insertToPropertyQNamesPS = connection.prepareStatement(vendor.toString(this.createInsertStatement(schemaName, DBNames.ALL_QNAMES_TABLE_NAME, AMOUNT_OF_COLUMNS_IN_ALL_QNAMES_TABLE, vendor)));
        clearEntityDataPS = connection.prepareStatement(this.createClearEntityDataStatement(schemaName, vendor).toString());
        Map<Long, EntityState> statesByPK = new HashMap<>();
        Map<Long, Integer> qNamePKs = new HashMap<>();
        Iterable<EntityState> relatedStates = Iterables.filter(new Specification<EntityState>() {

            @Override
            public boolean satisfiedBy(EntityState item) {
                return item.entityDescriptor().queryable();
            }
        }, Iterables.map(SQLCompatEntityStateWrapper.WRAP, changedStates));
        for (EntityState eState : relatedStates) {
            EntityStatus status = eState.status();
            Long pk = null;
            boolean needToInsert = status.equals(EntityStatus.NEW);
            if (!needToInsert) {
                if (status.equals(EntityStatus.UPDATED)) {
                    pk = this.findEntityPK(eState, queryEntityPKPS);
                    if (pk == null) {
                        // Happens when reindexing
                        needToInsert = true;
                    } else {
                        // TODO if multiple applications with different application model use
                        // indexing, need to sync type-table.
                        this.updateEntityInfoAndProperties(connection, qNameInsertPSs, insertToPropertyQNamesPS, clearEntityDataPS, updateEntityTablePS, eState, pk, qNamePKs);
                    }
                } else if (status.equals(EntityStatus.REMOVED)) {
                    this.removeEntity(eState, removeEntityPS);
                } else {
                // TODO possibly handle LOADED state somehow
                // throw new
                // UnsupportedOperationException("Did not understand what to do with state [id = "
                // +
                // eState.identity().identity() + ", status = " + status + "].");
                }
            }
            if (needToInsert) {
                pk = this.getPKFromAutoGeneratedIDInsert(eState, insertToEntityTableAutoGenerated.getValue(), vendor, connection);
                this.insertPropertyType(connection, insertToEntityTypeTablePS.getValue(), eState, pk);
                this.insertProperties(connection, qNameInsertPSs, insertToPropertyQNamesPS, eState, pk, qNamePKs);
            }
            if (pk != null) {
                statesByPK.put(pk, eState);
            }
        }
        removeEntityPS.executeBatch();
        updateEntityTablePS.executeBatch();
        clearEntityDataPS.executeBatch();
        if (insertToEntityTypeTablePS.hasValue()) {
            insertToEntityTypeTablePS.getValue().executeBatch();
        }
        for (Map.Entry<Long, EntityState> entry : statesByPK.entrySet()) {
            EntityState eState = entry.getValue();
            Long pk = entry.getKey();
            this.insertAssoAndManyAssoQNames(qNameInsertPSs, insertToPropertyQNamesPS, eState, qNamePKs.get(pk), pk);
        }
        insertToPropertyQNamesPS.executeBatch();
        for (PreparedStatement ps : qNameInsertPSs.values()) {
            ps.executeBatch();
        }
        connection.commit();
    } catch (SQLException sqle) {
        SQLUtil.rollbackQuietly(connection);
        throw sqle;
    } finally {
        try {
            if (queryEntityPKPS.hasValue()) {
                SQLUtil.closeQuietly(queryEntityPKPS.getValue());
            }
            if (insertToEntityTableAutoGenerated.hasValue()) {
                SQLUtil.closeQuietly(insertToEntityTableAutoGenerated.getValue());
            }
            SQLUtil.closeQuietly(updateEntityTablePS);
            SQLUtil.closeQuietly(removeEntityPS);
            SQLUtil.closeQuietly(insertToPropertyQNamesPS);
            SQLUtil.closeQuietly(clearEntityDataPS);
            for (PreparedStatement ps : qNameInsertPSs.values()) {
                SQLUtil.closeQuietly(ps);
            }
        } finally {
            if (connectionFromStartupWasNull) {
                SQLUtil.closeQuietly(connection);
            } else {
                connection.setReadOnly(wasReadOnly);
                connection.setAutoCommit(wasAutoCommit);
            }
        }
    }
}
Also used : SQLException(java.sql.SQLException) HashMap(java.util.HashMap) QualifiedName(org.qi4j.api.common.QualifiedName) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) EntityState(org.qi4j.spi.entity.EntityState) Lazy(org.qi4j.index.sql.support.skeletons.SQLSkeletonUtil.Lazy) EntityStatus(org.qi4j.spi.entity.EntityStatus) SQLVendor(org.sql.generation.api.vendor.SQLVendor) Map(java.util.Map) HashMap(java.util.HashMap)

Example 27 with QualifiedName

use of org.qi4j.api.common.QualifiedName in project qi4j-sdk by Qi4j.

the class AbstractSQLQuerying method traverseAssociationPath.

protected Integer traverseAssociationPath(TraversedAssoOrManyAssoRef reference, Integer lastTableIndex, Integer nextAvailableIndex, SQLVendor vendor, TableReferenceBuilder builder, JoinType joinStyle, Boolean includeLastTable) {
    Stack<QualifiedName> qNameStack = new Stack<>();
    TableReferenceFactory t = vendor.getTableReferenceFactory();
    BooleanFactory b = vendor.getBooleanFactory();
    ColumnsFactory c = vendor.getColumnsFactory();
    String schemaName = this._state.schemaName().get();
    while (reference._hasRefs) {
        qNameStack.add(QualifiedName.fromAccessor(reference.getAccessor()));
        reference = reference.getTraversedAssociation();
    }
    while (!qNameStack.isEmpty()) {
        QualifiedName qName = qNameStack.pop();
        QNameInfo info = this._state.qNameInfos().get().get(qName);
        if (info == null) {
            throw new InternalError("No qName info found for qName [" + qName + "].");
        }
        // @formatter:off
        builder.addQualifiedJoin(joinStyle, t.table(t.tableName(schemaName, info.getTableName()), t.tableAlias(TABLE_NAME_PREFIX + nextAvailableIndex)), t.jc(b.eq(c.colName(TABLE_NAME_PREFIX + lastTableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME), c.colName(TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))));
        lastTableIndex = nextAvailableIndex;
        ++nextAvailableIndex;
        if (includeLastTable || !qNameStack.isEmpty()) {
            builder.addQualifiedJoin(joinStyle, t.table(t.tableName(schemaName, DBNames.ENTITY_TABLE_NAME), t.tableAlias(TABLE_NAME_PREFIX + nextAvailableIndex)), t.jc(b.eq(c.colName(TABLE_NAME_PREFIX + lastTableIndex, DBNames.QNAME_TABLE_VALUE_COLUMN_NAME), c.colName(TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))));
            lastTableIndex = nextAvailableIndex;
            ++nextAvailableIndex;
        }
    // @formatter:on
    }
    return lastTableIndex;
}
Also used : TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory) QualifiedName(org.qi4j.api.common.QualifiedName) ColumnsFactory(org.sql.generation.api.grammar.factories.ColumnsFactory) QNameInfo(org.qi4j.index.sql.support.common.QNameInfo) BooleanFactory(org.sql.generation.api.grammar.factories.BooleanFactory) Stack(java.util.Stack)

Aggregations

QualifiedName (org.qi4j.api.common.QualifiedName)27 HashMap (java.util.HashMap)11 Map (java.util.Map)10 PropertyDescriptor (org.qi4j.api.property.PropertyDescriptor)10 EntityReference (org.qi4j.api.entity.EntityReference)9 ArrayList (java.util.ArrayList)8 List (java.util.List)7 AssociationDescriptor (org.qi4j.api.association.AssociationDescriptor)7 LinkedHashMap (java.util.LinkedHashMap)6 EntityDescriptor (org.qi4j.api.entity.EntityDescriptor)6 QNameInfo (org.qi4j.index.sql.support.common.QNameInfo)6 EntityStoreException (org.qi4j.spi.entitystore.EntityStoreException)6 Type (java.lang.reflect.Type)5 Member (java.lang.reflect.Member)4 JSONArray (org.json.JSONArray)4 JSONException (org.json.JSONException)4 JSONObject (org.json.JSONObject)4 AccessibleObject (java.lang.reflect.AccessibleObject)3 TypeVariable (java.lang.reflect.TypeVariable)3 HashSet (java.util.HashSet)3