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

org.datanucleus.store.rdbms.query.ResultMetaDataROF Maven / Gradle / Ivy

There is a newer version: 6.0.7
Show newest version
/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
Licensed 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.

Contributors:
    ...
**********************************************************************/
package org.datanucleus.store.rdbms.query;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.datanucleus.ExecutionContext;
import org.datanucleus.FetchPlan;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.identity.IdentityUtils;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.metadata.QueryResultMetaData;
import org.datanucleus.metadata.QueryResultMetaData.ConstructorTypeColumn;
import org.datanucleus.metadata.QueryResultMetaData.ConstructorTypeMapping;
import org.datanucleus.metadata.QueryResultMetaData.PersistentTypeMapping;
import org.datanucleus.state.ObjectProvider;
import org.datanucleus.store.FieldValues;
import org.datanucleus.store.fieldmanager.FieldManager;
import org.datanucleus.store.rdbms.mapping.StatementClassMapping;
import org.datanucleus.store.rdbms.mapping.StatementMappingIndex;
import org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping;
import org.datanucleus.store.rdbms.table.Column;
import org.datanucleus.store.rdbms.table.DatastoreClass;
import org.datanucleus.store.rdbms.RDBMSStoreManager;
import org.datanucleus.util.ClassUtils;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.StringUtils;
import org.datanucleus.util.TypeConversionHelper;

/**
 * ResultObjectFactory that operates using a QueryResultMetaData and returns objects based on the definition.
 * A QueryResultMetaData allows for a row of a ResultSet to be returned as a mix of :-
 * 
    *
  • a number of persistent objects (made up of several ResultSet columns)
  • *
  • a number of Objects (from individual ResultSet columns)
  • *
* Each call to getObject() will then return a set of objects as per the MetaData definition. *

ResultSet to object mapping

* Each row of the ResultSet has a set of columns, and these columns are either used for direct outputting * back to the user as a "simple" object, or as a field in a persistent object. So you could have a situation * like this :- *
 * ResultSet Column   Output Object
 * ================   =============
 * COL1               PC1.field1
 * COL2               PC1.field2
 * COL3               Simple Object
 * COL4               PC2.field3
 * COL5               PC2.field1
 * COL6               PC2.field2
 * COL7               Simple Object
 * COL8               PC1.field3
 * ...
 * 
* So this example will return an Object[4] ... Object[0] = instance of PC1, Object[1] = instance of PC2, * Object[2] = simple object, Object[3] = simple object. * When creating the instance of PC1 we take the ResultSet columns (COL1, COL2, COL8). * When creating the instance of PC2 we take the ResultSet columns (COL5, COL6, COL4). */ public class ResultMetaDataROF implements ResultObjectFactory { RDBMSStoreManager storeMgr; /** MetaData defining the result from the Query. */ QueryResultMetaData queryResultMetaData = null; String[] columnNames = null; private boolean ignoreCache = false; /** * Constructor. * @param storeMgr RDBMS StoreManager * @param qrmd MetaData defining the results from the query. */ public ResultMetaDataROF(RDBMSStoreManager storeMgr, QueryResultMetaData qrmd) { this.storeMgr = storeMgr; this.queryResultMetaData = qrmd; } /** * Accessor for the object(s) from a row of the ResultSet. * @param ec execution context * @param rs ResultSet * @return The object(s) for this row of the ResultSet. */ public Object getObject(ExecutionContext ec, ResultSet rs) { List returnObjects = new ArrayList(); if (columnNames == null) { try { //obtain column names ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); columnNames = new String[columnCount]; for( int i=0; i ctrColumns = ctrTypeMappings[i].getColumnsForConstructor(); Class[] ctrArgTypes = null; Object[] ctrArgVals = null; if (ctrColumns != null && ctrColumns.size() > 0) { int j=0; ctrArgTypes = new Class[ctrColumns.size()]; ctrArgVals = new Object[ctrColumns.size()]; Iterator colIter = ctrColumns.iterator(); while (colIter.hasNext()) { ConstructorTypeColumn ctrCol = colIter.next(); try { Object colVal = getResultObject(rs, ctrCol.getColumnName()); ctrArgTypes[j] = colVal.getClass(); if (ctrCol.getJavaType() != null) { // Attempt to convert to the type requested ctrArgTypes[j] = ctrCol.getJavaType(); ctrArgVals[j] = TypeConversionHelper.convertTo(colVal, ctrArgTypes[j]); } else { ctrArgTypes[j] = colVal.getClass(); ctrArgVals[j] = colVal; } } catch (SQLException sqle) { // TODO Handle this } j++; } } returnObjects.add(ClassUtils.newInstance(ctrCls, ctrArgTypes, ctrArgVals)); } } if (returnObjects.size() == 0) { // No objects so user must have supplied incorrect MetaData return null; } else if (returnObjects.size() == 1) { // Return Object return returnObjects.get(0); } else { // Return Object[] return returnObjects.toArray(new Object[returnObjects.size()]); } } /** * Convenience method to read the value of a column out of the ResultSet. * @param rs ResultSet * @param columnName Name of the column * @return Value for the column for this row. * @throws SQLException Thrown if an error occurs on reading */ private Object getResultObject(final ResultSet rs, String columnName) throws SQLException { return rs.getObject(columnName); } /** * Returns a PC instance from a ResultSet row with an application identity. * @param ec execution context * @param rs The ResultSet * @param fieldNumbers Numbers of the fields (of the class) found in the ResultSet * @param cmd MetaData for the class * @param pcClass persistable class * @param requiresInheritanceCheck Whether we need to check the inheritance level of the returned object * @param stmtMappings mappings for the results in the statement * @return The object with this application identity */ private Object getObjectForApplicationId(final ExecutionContext ec, final ResultSet rs, final int[] fieldNumbers, AbstractClassMetaData cmd, Class pcClass, boolean requiresInheritanceCheck, StatementMappingIndex[] stmtMappings) { final StatementClassMapping resultMappings = new StatementClassMapping(); for (int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy