Search in sources :

Example 6 with EntityStatus

use of org.qi4j.spi.entity.EntityStatus 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)

Aggregations

EntityStatus (org.qi4j.spi.entity.EntityStatus)6 EntityStoreException (org.qi4j.spi.entitystore.EntityStoreException)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 QualifiedName (org.qi4j.api.common.QualifiedName)4 EntityDescriptor (org.qi4j.api.entity.EntityDescriptor)4 Module (org.qi4j.api.structure.Module)4 EntityTypeNotFoundException (org.qi4j.api.unitofwork.EntityTypeNotFoundException)4 ArrayList (java.util.ArrayList)3 LinkedHashMap (java.util.LinkedHashMap)3 List (java.util.List)3 JSONException (org.json.JSONException)3 JSONObject (org.json.JSONObject)3 JSONTokener (org.json.JSONTokener)3 AssociationDescriptor (org.qi4j.api.association.AssociationDescriptor)3 EntityReference (org.qi4j.api.entity.EntityReference)3 PropertyDescriptor (org.qi4j.api.property.PropertyDescriptor)3 DefaultEntityState (org.qi4j.spi.entitystore.helpers.DefaultEntityState)3 Connection (java.sql.Connection)2 PreparedStatement (java.sql.PreparedStatement)2