Search in sources :

Example 1 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getElementMapping.

/**
 * Convenience accessor for the element mapping for the element of a collection/array of elements.
 * @param table The table
 * @param mmd MetaData for the collection member containing the collection/array of PCs
 * @param fieldRole role of this mapping for this member
 * @param clr ClassLoader resolver
 * @return The mapping
 */
protected JavaTypeMapping getElementMapping(Table table, AbstractMemberMetaData mmd, FieldRole fieldRole, ClassLoaderResolver clr) {
    if (!mmd.hasCollection() && !mmd.hasArray()) {
        // TODO Localise this message
        throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no collection/array!").setFatal();
    }
    if (mmd.getJoinMetaData() == null) {
        AbstractMemberMetaData[] refMmds = mmd.getRelatedMemberMetaData(clr);
        if (refMmds == null || refMmds.length == 0) {
            // TODO Localise this
            throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no join table defined for the collection/array").setFatal();
        }
        if (refMmds[0].getJoinMetaData() == null) {
            // TODO Localise this
            throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no join table defined for the collection/array").setFatal();
        }
    }
    MappingConverterDetails mcd = null;
    Class mc = null;
    String userMappingClassName = null;
    String userTypeConverterName = null;
    if (mmd.getElementMetaData() != null) {
        userTypeConverterName = mmd.getElementMetaData().getValueForExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME);
        userMappingClassName = mmd.getElementMetaData().getValueForExtension("mapping-class");
    }
    if (userTypeConverterName != null) {
        TypeConverter conv = storeMgr.getNucleusContext().getTypeManager().getTypeConverterForName(userTypeConverterName);
        if (conv == null) {
            throw new NucleusUserException("Field " + mmd.getFullFieldName() + " ELEMENT has been specified to use type converter " + userTypeConverterName + " but not found!");
        }
        // TODO Could be TypeConverterMultiMapping?
        mcd = new MappingConverterDetails(TypeConverterMapping.class, conv);
    } else if (userMappingClassName != null) {
        // User has defined their own mapping class for this element so use that
        try {
            mc = clr.classForName(userMappingClassName);
        } catch (NucleusException jpe) {
            throw new NucleusUserException(Localiser.msg("041014", userMappingClassName)).setFatal();
        }
    } else {
        boolean serialised = ((mmd.hasCollection() && mmd.getCollection().isSerializedElement()) || (mmd.hasArray() && mmd.getArray().isSerializedElement()));
        boolean embeddedPC = (mmd.hasCollection() && mmd.getCollection().elementIsPersistent() && mmd.getCollection().isEmbeddedElement()) || (mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null);
        boolean elementPC = ((mmd.hasCollection() && mmd.getCollection().elementIsPersistent()) || (mmd.hasArray() && mmd.getArray().elementIsPersistent()));
        boolean embedded = true;
        if (mmd.hasCollection()) {
            embedded = mmd.getCollection().isEmbeddedElement();
        } else if (mmd.hasArray()) {
            embedded = mmd.getArray().isEmbeddedElement();
        }
        Class elementCls = null;
        if (mmd.hasCollection()) {
            elementCls = clr.classForName(mmd.getCollection().getElementType());
        } else if (mmd.hasArray()) {
            // Use declared element type rather than any restricted type specified in metadata
            elementCls = mmd.getType().getComponentType();
        }
        boolean elementReference = ClassUtils.isReferenceType(elementCls);
        if (serialised) {
            if (elementPC) {
                // Serialised PC element
                mc = SerialisedElementPCMapping.class;
            } else if (elementReference) {
                // Serialised Reference element
                mc = SerialisedReferenceMapping.class;
            } else {
                // Serialised Non-PC element
                mc = SerialisedMapping.class;
            }
        } else if (embedded) {
            if (embeddedPC) {
                // Embedded PC type
                mc = EmbeddedElementPCMapping.class;
            } else if (elementPC) {
                // "Embedded" PC type but no <embedded> so dont embed for now. Is this correct?
                mc = PersistableMapping.class;
            } else {
                // Embedded Non-PC type
                mcd = getMappingClass(elementCls, serialised, embedded, mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null, mmd.getFullFieldName());
            }
        } else {
            // Normal element mapping
            mcd = getMappingClass(elementCls, serialised, embedded, mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null, mmd.getFullFieldName());
        }
    }
    if (mcd != null && mcd.typeConverter == null) {
        mc = mcd.mappingClass;
    }
    if (mc != null && (mcd == null || mcd.typeConverter == null)) {
        // Create the mapping of the selected type
        JavaTypeMapping m = null;
        try {
            m = (JavaTypeMapping) mc.newInstance();
            m.setRoleForMember(fieldRole);
            m.initialize(mmd, table, clr);
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    } else if (mcd != null && mcd.typeConverter != null) {
        try {
            JavaTypeMapping m = (JavaTypeMapping) mcd.mappingClass.newInstance();
            m.setRoleForMember(fieldRole);
            if (m instanceof TypeConverterMapping) {
                ((TypeConverterMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            } else if (m instanceof TypeConverterMultiMapping) {
                ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc != null ? mc.getName() : null, e), e).setFatal();
        }
    }
    throw new NucleusException("Unable to create mapping for element of collection/array at " + mmd.getFullFieldName() + " - no available mapping");
}
Also used : SerialisedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedElementPCMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) NucleusException(org.datanucleus.exceptions.NucleusException) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) TypeConverterMultiMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMultiMapping)

Example 2 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getMapping.

/**
 * Accessor for the mapping for the member of the specified table.
 * Can be used for members of a class, element of a collection of a class, element of an array of a class,
 * keys of a map of a class, values of a map of a class; this is controlled by the role argument.
 * @param table Table to add the mapping to
 * @param mmd MetaData for the member to map
 * @param clr The ClassLoaderResolver
 * @param fieldRole Role that this mapping plays for the field
 * @return The mapping for the member.
 */
public JavaTypeMapping getMapping(Table table, AbstractMemberMetaData mmd, ClassLoaderResolver clr, FieldRole fieldRole) {
    if (fieldRole == FieldRole.ROLE_COLLECTION_ELEMENT || fieldRole == FieldRole.ROLE_ARRAY_ELEMENT) {
        // Mapping a collection/array element (in a join table)
        return getElementMapping(table, mmd, fieldRole, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_KEY) {
        // Mapping a map key (in a join table)
        return getKeyMapping(table, mmd, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_VALUE) {
        // Mapping a map value (in a join table)
        return getValueMapping(table, mmd, clr);
    }
    // Check for use of TypeConverter (either specific, or auto-apply for this type)
    TypeManager typeMgr = table.getStoreManager().getNucleusContext().getTypeManager();
    TypeConverter conv = null;
    if (!mmd.isTypeConversionDisabled()) {
        // User-specified TypeConverter defined for the whole member, or an autoApply is present for this member type
        if (mmd.getTypeConverterName() != null) {
            conv = typeMgr.getTypeConverterForName(mmd.getTypeConverterName());
            if (conv == null) {
                throw new NucleusUserException(Localiser.msg("044062", mmd.getFullFieldName(), mmd.getTypeConverterName()));
            }
        } else {
            TypeConverter autoApplyConv = typeMgr.getAutoApplyTypeConverterForType(mmd.getType());
            if (autoApplyConv != null) {
                conv = autoApplyConv;
            }
        }
        if (conv != null) {
            // Create the mapping of the selected type
            JavaTypeMapping m = null;
            if (conv instanceof MultiColumnConverter) {
                Class mc = TypeConverterMultiMapping.class;
                try {
                    m = (JavaTypeMapping) mc.newInstance();
                    m.setRoleForMember(FieldRole.ROLE_FIELD);
                    ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, conv);
                    return m;
                } catch (Exception e) {
                    throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
                }
            }
            Class mc = TypeConverterMapping.class;
            try {
                m = (JavaTypeMapping) mc.newInstance();
                m.setRoleForMember(FieldRole.ROLE_FIELD);
                ((TypeConverterMapping) m).initialize(mmd, table, clr, conv);
                return m;
            } catch (Exception e) {
                throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
            }
        }
    }
    AbstractMemberMetaData overrideMmd = null;
    MappingConverterDetails mcd = null;
    Class mc = null;
    String userMappingClassName = mmd.getValueForExtension("mapping-class");
    if (userMappingClassName != null) {
        // User has defined their own mapping class for this field so use that
        try {
            mc = clr.classForName(userMappingClassName);
        } catch (NucleusException ne) {
            throw new NucleusUserException(Localiser.msg("041014", mmd.getFullFieldName(), userMappingClassName)).setFatal();
        }
    } else {
        AbstractClassMetaData typeCmd = null;
        if (mmd.getType().isInterface()) {
            typeCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForInterface(mmd.getType(), clr);
        } else {
            typeCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
        }
        if (mmd.hasExtension(SerialisedLocalFileMapping.EXTENSION_SERIALIZE_TO_FOLDER) && Serializable.class.isAssignableFrom(mmd.getType())) {
            // Special case : use file serialization mapping
            mc = SerialisedLocalFileMapping.class;
        } else if (mmd.isSerialized()) {
            // Field is marked as serialised then we have no other option - serialise it
            mcd = getMappingClass(mmd.getType(), true, false, null, mmd.getFullFieldName());
        } else if (mmd.getEmbeddedMetaData() != null) {
            // Field has an <embedded> specification so use that
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (typeCmd != null && typeCmd.isEmbeddedOnly()) {
            // Reference type is declared with embedded only
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (// TODO Check this since it will push all basic nonPC fields through here
        mmd.isEmbedded()) {
            // Otherwise, if the field is embedded then we request that it be serialised into the owner table
            // This is particularly for java.lang.Object which should be "embedded" by default, and hence serialised
            mcd = getMappingClass(mmd.getType(), true, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
        } else {
            // Non-embedded/non-serialised - Just get the basic mapping for the type
            Class memberType = mmd.getType();
            mcd = getMappingClass(memberType, false, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
            if (mmd.getParent() instanceof EmbeddedMetaData && mmd.getRelationType(clr) != RelationType.NONE) {
                // See NUCCORE-697 - always need to use the real member metadata for the mapping
                // so that it can find sub-fields when persisting/querying etc
                AbstractClassMetaData cmdForFmd = table.getStoreManager().getMetaDataManager().getMetaDataForClass(mmd.getClassName(), clr);
                overrideMmd = cmdForFmd.getMetaDataForMember(mmd.getName());
            }
        }
    }
    // Create the mapping of the selected type
    if (mcd != null) {
        mc = mcd.mappingClass;
        // Allow override by Oracle
        mc = getOverrideMappingClass(mc, mmd, fieldRole);
    }
    if (mc != null && (mcd == null || mcd.typeConverter == null)) {
        try {
            JavaTypeMapping m = (JavaTypeMapping) mc.newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            m.initialize(mmd, table, clr);
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    } else if (mcd != null && mcd.typeConverter != null) {
        try {
            JavaTypeMapping m = (JavaTypeMapping) mcd.mappingClass.newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            if (m instanceof TypeConverterMapping) {
                ((TypeConverterMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            } else if (m instanceof TypeConverterMultiMapping) {
                ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            }
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    }
    throw new NucleusException("Unable to create mapping for member at " + mmd.getFullFieldName() + " - no available mapping");
}
Also used : Serializable(java.io.Serializable) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) MultiColumnConverter(org.datanucleus.store.types.converters.MultiColumnConverter) NucleusException(org.datanucleus.exceptions.NucleusException) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) TypeManager(org.datanucleus.store.types.TypeManager) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) TypeConverterMultiMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMultiMapping)

Example 3 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class ArrayRDBMSMapping method getObject.

public Object getObject(ResultSet rs, int param) {
    Object value = null;
    try {
        Array arr = rs.getArray(param);
        if (!rs.wasNull()) {
            Object javaArray = arr.getArray();
            int length = java.lang.reflect.Array.getLength(javaArray);
            AbstractMemberMetaData mmd = mapping.getMemberMetaData();
            if (mmd.getType().isArray()) {
                // Copy in to an array of the same type as the member
                value = java.lang.reflect.Array.newInstance(mmd.getType().getComponentType(), length);
                for (int i = 0; i < length; i++) {
                    java.lang.reflect.Array.set(value, i, java.lang.reflect.Array.get(javaArray, i));
                }
            } else if (Collection.class.isAssignableFrom(mmd.getType())) {
                Collection<Object> coll;
                try {
                    Class instanceType = SCOUtils.getContainerInstanceType(mmd.getType(), mmd.getOrderMetaData() != null);
                    coll = (Collection<Object>) instanceType.newInstance();
                } catch (Exception e) {
                    throw new NucleusDataStoreException(e.getMessage(), e);
                }
                for (int i = 0; i < length; i++) {
                    coll.add(java.lang.reflect.Array.get(javaArray, i));
                }
                value = coll;
            } else {
                throw new NucleusUserException("We do not support retrieving values of type " + mmd.getTypeName() + " as an ARRAY." + " Member=" + mapping.getMemberMetaData().getFullFieldName());
            }
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException(Localiser.msg("055002", "Object", "" + param, column, e.getMessage()), e);
    }
    return value;
}
Also used : Array(java.sql.Array) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLException(java.sql.SQLException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) Collection(java.util.Collection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLException(java.sql.SQLException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException)

Example 4 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class OracleClobRDBMSMapping method updateClobColumn.

/**
 * Convenience method to update the contents of a CLOB column.
 * Oracle requires that a CLOB is initialised with EMPTY_CLOB() and then you retrieve
 * the column and update its CLOB value. Performs a statement
 * <pre>
 * SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE
 * </pre>
 * and then updates the Clob value returned.
 * @param op ObjectProvider of the object
 * @param table Table storing the CLOB column
 * @param mapping Datastore mapping for the CLOB column
 * @param value The value to store in the CLOB
 * @throws NucleusObjectNotFoundException Thrown if an object is not found
 * @throws NucleusDataStoreException Thrown if an error occurs in datastore communication
 */
@SuppressWarnings("deprecation")
public static void updateClobColumn(ObjectProvider op, Table table, DatastoreMapping mapping, String value) {
    ExecutionContext ec = op.getExecutionContext();
    RDBMSStoreManager storeMgr = table.getStoreManager();
    // Don't support join tables yet
    DatastoreClass classTable = (DatastoreClass) table;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    // Generate "SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
    SelectStatement sqlStmt = new SelectStatement(storeMgr, table, null, null);
    sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver());
    sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    SQLTable blobSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), mapping.getJavaTypeMapping());
    sqlStmt.select(blobSqlTbl, mapping.getColumn(), null);
    StatementClassMapping mappingDefinition = new StatementClassMapping();
    AbstractClassMetaData cmd = op.getClassMetaData();
    int inputParamNum = 1;
    if (cmd.getIdentityType() == IdentityType.DATASTORE) {
        // Datastore identity value for input
        JavaTypeMapping datastoreIdMapping = classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), datastoreIdMapping);
        SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, datastoreIdMapping, null, "ID");
        sqlStmt.whereAnd(expr.eq(val), true);
        StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
        if (datastoreIdx == null) {
            datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
        }
        datastoreIdx.addParameterOccurrence(new int[] { inputParamNum });
    } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // Application identity value(s) for input
        int[] pkNums = cmd.getPKMemberPositions();
        for (int i = 0; i < pkNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
            JavaTypeMapping pkMapping = classTable.getMemberMapping(mmd);
            SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), pkMapping);
            SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, pkMapping, null, "PK" + i);
            sqlStmt.whereAnd(expr.eq(val), true);
            StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNums[i]);
            if (pkIdx == null) {
                pkIdx = new StatementMappingIndex(pkMapping);
                mappingDefinition.addMappingForMember(pkNums[i], pkIdx);
            }
            int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
            for (int j = 0; j < pkMapping.getNumberOfDatastoreMappings(); j++) {
                inputParams[j] = inputParamNum++;
            }
            pkIdx.addParameterOccurrence(inputParams);
        }
    }
    String textStmt = sqlStmt.getSQLText().toSQL();
    if (op.isEmbedded()) {
        // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
        ObjectProvider[] embeddedOwners = ec.getOwnersForEmbeddedObjectProvider(op);
        if (embeddedOwners != null) {
            // Just use the first owner
            // TODO Should check if the owner is stored in this table
            op = embeddedOwners[0];
        }
    }
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
            try {
                // Provide the primary key field(s) to the JDBC statement
                if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                    StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                    for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
                        classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
                    }
                } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                    op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
                }
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
                try {
                    if (!rs.next()) {
                        throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
                    }
                    DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
                    int jdbcMajorVersion = dba.getDriverMajorVersion();
                    if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
                        // Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific CLOB type
                        // we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
                        oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob(1);
                        if (clob != null) {
                            // Deprecated but what can you do
                            clob.putString(1, value);
                        }
                    } else {
                        // Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Clobs
                        java.sql.Clob clob = rs.getClob(1);
                        if (clob != null) {
                            clob.setString(1, value);
                        }
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException("Update of CLOB value failed: " + textStmt, e);
    }
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) PreparedStatement(java.sql.PreparedStatement) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) DatastoreAdapter(org.datanucleus.store.rdbms.adapter.DatastoreAdapter) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 5 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.

the class EmbeddedMapping method initialize.

/**
 * Initialize for the specified member.
 * @param mmd metadata for the embedded member
 * @param table Table for persisting this field
 * @param clr The ClassLoaderResolver
 * @param emd Embedded MetaData for the object being embedded
 * @param typeName type of the embedded PC object being stored
 * @param objectType Object type of the PC object being embedded (see StateManagerImpl object types)
 */
public void initialize(AbstractMemberMetaData mmd, Table table, ClassLoaderResolver clr, EmbeddedMetaData emd, String typeName, int objectType) {
    super.initialize(mmd, table, clr);
    this.clr = clr;
    this.emd = emd;
    this.typeName = typeName;
    this.objectType = (short) objectType;
    // Find the MetaData for the embedded PC class
    MetaDataManager mmgr = table.getStoreManager().getMetaDataManager();
    AbstractClassMetaData rootEmbCmd = mmgr.getMetaDataForClass(typeName, clr);
    if (rootEmbCmd == null) {
        // Not found so must be an interface
        // Try using the fieldTypes on the field/property - we support it if only 1 implementation
        String[] fieldTypes = mmd.getFieldTypes();
        if (fieldTypes != null && fieldTypes.length == 1) {
            rootEmbCmd = mmgr.getMetaDataForClass(fieldTypes[0], clr);
        } else if (fieldTypes != null && fieldTypes.length > 1) {
            // TODO Cater for multiple implementations
            throw new NucleusUserException("Field " + mmd.getFullFieldName() + " is a reference field that is embedded with multiple possible implementations. " + "DataNucleus doesnt support embedded reference fields that have more than 1 implementation");
        }
        if (rootEmbCmd == null) {
            // Try a persistent interface
            rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(typeName), clr);
            if (rootEmbCmd == null && mmd.getFieldTypes() != null && mmd.getFieldTypes().length == 1) {
                // No MetaData for the type so try "fieldType" specified on the field
                rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(mmd.getFieldTypes()[0]), clr);
            }
        }
    }
    if (rootEmbCmd == null) {
        throw new NucleusUserException("Unable to find root class embedded metadata for field=" + mmd.getFullFieldName());
    }
    embCmd = rootEmbCmd;
    AbstractMemberMetaData[] embFmds = null;
    if (emd == null && rootEmbCmd.isEmbeddedOnly()) {
        // No <embedded> block yet the class is defined as embedded-only so just use its own definition of fields
        embFmds = rootEmbCmd.getManagedMembers();
    } else if (emd != null) {
        // <embedded> block so use those field definitions
        embFmds = emd.getMemberMetaData();
    }
    String[] subclasses = mmgr.getSubclassesForClass(rootEmbCmd.getFullClassName(), true);
    if (subclasses != null && subclasses.length > 0) {
        if (rootEmbCmd.hasDiscriminatorStrategy()) {
            // Fabricate a DiscriminatorMetaData to use for the embedded object
            discrimMetaData = new DiscriminatorMetaData();
            InheritanceMetaData embInhMd = new InheritanceMetaData();
            embInhMd.setParent(rootEmbCmd);
            discrimMetaData.setParent(embInhMd);
            // Set strategy based on the inheritance of the embedded object, otherwise class name.
            DiscriminatorMetaData dismd = rootEmbCmd.getDiscriminatorMetaDataRoot();
            if (dismd.getStrategy() != null && dismd.getStrategy() != DiscriminatorStrategy.NONE) {
                discrimMetaData.setStrategy(dismd.getStrategy());
            } else {
                // Fallback to class name
                discrimMetaData.setStrategy(DiscriminatorStrategy.CLASS_NAME);
            }
            // Set column for discriminator
            ColumnMetaData disColmd = new ColumnMetaData();
            disColmd.setAllowsNull(Boolean.TRUE);
            DiscriminatorMetaData embDismd = (emd != null) ? emd.getDiscriminatorMetaData() : null;
            if (embDismd != null && embDismd.getColumnMetaData() != null) {
                disColmd.setName(embDismd.getColumnMetaData().getName());
            } else {
                ColumnMetaData colmd = dismd.getColumnMetaData();
                if (colmd != null && colmd.getName() != null) {
                    disColmd.setName(colmd.getName());
                }
            }
            discrimMetaData.setColumnMetaData(disColmd);
            discrimMapping = DiscriminatorMapping.createDiscriminatorMapping(table, discrimMetaData);
            addDatastoreMapping(discrimMapping.getDatastoreMapping(0));
        } else {
            NucleusLogger.PERSISTENCE.info("Member " + mmd.getFullFieldName() + " is embedded and the type " + "(" + rootEmbCmd.getFullClassName() + ") has potential subclasses." + " Impossible to detect which is stored embedded. Add a discriminator to the embedded type");
        }
    }
    // Add all fields of the embedded class (that are persistent)
    int[] pcFieldNumbers = rootEmbCmd.getAllMemberPositions();
    for (int i = 0; i < pcFieldNumbers.length; i++) {
        AbstractMemberMetaData rootEmbMmd = rootEmbCmd.getMetaDataForManagedMemberAtAbsolutePosition(pcFieldNumbers[i]);
        if (rootEmbMmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
            addMappingForMember(rootEmbCmd, rootEmbMmd, embFmds);
        }
    }
    // Add fields for any subtypes (that are persistent)
    if (discrimMapping != null && subclasses != null && subclasses.length > 0) {
        for (int i = 0; i < subclasses.length; i++) {
            AbstractClassMetaData subEmbCmd = storeMgr.getMetaDataManager().getMetaDataForClass(subclasses[i], clr);
            AbstractMemberMetaData[] subEmbMmds = subEmbCmd.getManagedMembers();
            if (subEmbMmds != null) {
                for (int j = 0; j < subEmbMmds.length; j++) {
                    if (subEmbMmds[j].getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
                        addMappingForMember(subEmbCmd, subEmbMmds[j], embFmds);
                    }
                }
            }
        }
    }
}
Also used : DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) MetaDataManager(org.datanucleus.metadata.MetaDataManager) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) InheritanceMetaData(org.datanucleus.metadata.InheritanceMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Aggregations

AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)267 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)89 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)84 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)82 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)59 ClassMetaData (org.datanucleus.metadata.ClassMetaData)55 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)50 NucleusException (org.datanucleus.exceptions.NucleusException)41 MetaDataManager (org.datanucleus.metadata.MetaDataManager)40 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)38 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)35 RelationType (org.datanucleus.metadata.RelationType)33 NucleusContext (org.datanucleus.NucleusContext)32 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)32 JPAMetaDataManager (org.datanucleus.api.jpa.metadata.JPAMetaDataManager)29 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)28 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)27 ExecutionContext (org.datanucleus.ExecutionContext)26 ObjectProvider (org.datanucleus.state.ObjectProvider)25 ArrayList (java.util.ArrayList)24