All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.jdbc.kernel.FinderQueryImpl Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.openjpa.jdbc.kernel;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.Joinable;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.LogicalUnion;
import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.jdbc.sql.SelectImpl;
import org.apache.openjpa.jdbc.sql.Union;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.FinderQuery;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StoreManager;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.Id;


/**
 * Implements Finder Query identified by ClassMappping for SelectExecutor that 
 * can be executed to generate Result. 
 *  
 * @author Pinaki Poddar
 *
 * @since 2.0.0
 */
public class FinderQueryImpl 
    implements FinderQuery {
    private final ClassMapping _mapping;
    private final SelectImpl _select;
    private final Column[] _pkCols;
    private final Joinable[]  _joins;
    private final int[] _pkIndices;
    private final SQLBuffer _buffer;
    private final String _sql;
    
    /**
     * Attempts to construct a FinderQuery from the given Select for the given
     * mapping. The given Select may not be amenable for caching and then a null
     * value is returned. 
     */
    static FinderQueryImpl newFinder(ClassMapping mapping,
        SelectExecutor select) {
        SelectImpl impl = extractImplementation(select);
        if (impl == null)
            return null;
        SQLBuffer buffer = impl.getSQL();
        Column[] pkCols = mapping.getPrimaryKeyColumns();

        //OPENJPA-2557: Typically the number of pkCols (length) should match the number (size) of 
        //parameters.  However, there are a few cases (e.g. when extra parameters are needed for
        //discriminator data) where the pkCols length may be different than the parameters.   
        //If we find the number of pkCols is equal to the number of parameters, we need to do
        //one last check to verify that the buffers columns match the pkCols exactly.
        boolean canCache = (pkCols.length == buffer.getParameters().size());
        for(int i=0; i < pkCols.length  && canCache; i++){
            canCache = canCache && buffer.getColumns().contains(pkCols[i]);            
        }
        
        return (canCache)
            ? new FinderQueryImpl(mapping, impl, buffer) : null;
    }

    private FinderQueryImpl(ClassMapping mapping, SelectImpl select,
        SQLBuffer buffer) {
        super();
        _mapping = mapping;
        _select = select;
        _buffer = buffer;
        _sql = _buffer.getSQL();
        _pkCols = _mapping.getPrimaryKeyColumns();
        _joins = new Joinable[_pkCols.length];
        for (int i = 0; i < _pkCols.length; i++)
            _joins[i] = _mapping.assertJoinable(_pkCols[i]);
        _pkIndices = new int[_pkCols.length];
        for (int i = 0; i < _pkCols.length; i++) {
            FieldMetaData pk = _mapping.getField(_joins[i].getFieldIndex());
            _pkIndices[i] = pk == null ? 0 : pk.getPrimaryKeyIndex();
        }
        
    }
    
    public ClassMapping getIdentifier() {
        return _mapping;
    }
    
    public SelectExecutor getDelegate() {
        return _select;
    }
    
    public String getQueryString() {
        return _sql;
    }
    
    public Column[] getPKColumns() {
        return _pkCols;
    }
    
    private Object[] getPKValues(OpenJPAStateManager sm, JDBCStore store) {
        Object[] pks = null;
        Object oid = sm.getObjectId();
        if (_mapping.getIdentityType() == ClassMapping.ID_APPLICATION)
            pks = ApplicationIds.toPKValues(oid, _mapping);
    
        Object[] val = new Object[_pkCols.length];
        int count = 0;
        for (int i = 0; i < _pkCols.length; i++, count++) {
            if (pks == null)
                val[0] = (oid == null) 
                    ? null : ((Id) oid).getId();
            else {
                val[i] = _joins[i].getJoinValue(pks[_pkIndices[i]], _pkCols[i], 
                    store);
            }
        }
        return val;
    }
    
    public Result execute(OpenJPAStateManager sm, StoreManager store, 
        FetchConfiguration fetch) {
        boolean forUpdate = false;
        JDBCStore jstore = (JDBCStore)store;
        Connection conn = jstore.getConnection();
        DBDictionary dict = jstore.getDBDictionary();
        PreparedStatement stmnt = null;
        ResultSet rs = null;
        try {
            stmnt = _select.prepareStatement(conn, _sql);
            Object[] params = getPKValues(sm, jstore);
            if (stmnt != null) {
                for (int i = 0; i 




© 2015 - 2024 Weber Informatics LLC | Privacy Policy