/** * Method to create a PreparedStatement for use with the query. * * @param conn the Connection * @param queryStmt The statement text for the query * @param query The query * @return the PreparedStatement * @throws SQLException Thrown if an error occurs creating the statement */ public static PreparedStatement getPreparedStatementForQuery( ManagedConnection conn, String queryStmt, Query query) throws SQLException { // Apply any non-standard result set definition if required (either from the PMF, or via query // extensions) String rsTypeString = RDBMSQueryUtils.getResultSetTypeForQuery(query); if (rsTypeString != null && (!rsTypeString.equals("scroll-sensitive") && !rsTypeString.equals("forward-only") && !rsTypeString.equals("scroll-insensitive"))) { throw new NucleusUserException(LOCALISER.msg("052510")); } if (rsTypeString != null) { DatastoreAdapter dba = ((RDBMSStoreManager) query.getStoreManager()).getDatastoreAdapter(); // Add checks on what the DatastoreAdapter supports if (rsTypeString.equals("scroll-sensitive") && !dba.supportsOption(DatastoreAdapter.RESULTSET_TYPE_SCROLL_SENSITIVE)) { NucleusLogger.DATASTORE_RETRIEVE.info( "Query requested to run with result-set type of " + rsTypeString + " yet not supported by adapter. Using forward-only"); rsTypeString = "forward-only"; } else if (rsTypeString.equals("scroll-insensitive") && !dba.supportsOption(DatastoreAdapter.RESULTSET_TYPE_SCROLL_INSENSITIVE)) { NucleusLogger.DATASTORE_RETRIEVE.info( "Query requested to run with result-set type of " + rsTypeString + " yet not supported by adapter. Using forward-only"); rsTypeString = "forward-only"; } else if (rsTypeString.equals("forward-only") && !dba.supportsOption(DatastoreAdapter.RESULTSET_TYPE_FORWARD_ONLY)) { NucleusLogger.DATASTORE_RETRIEVE.info( "Query requested to run with result-set type of " + rsTypeString + " yet not supported by adapter. Using scroll-sensitive"); rsTypeString = "scroll-sensitive"; } } String rsConcurrencyString = RDBMSQueryUtils.getResultSetConcurrencyForQuery(query); if (rsConcurrencyString != null && (!rsConcurrencyString.equals("read-only") && !rsConcurrencyString.equals("updateable"))) { throw new NucleusUserException(LOCALISER.msg("052511")); } SQLController sqlControl = ((RDBMSStoreManager) query.getStoreManager()).getSQLController(); PreparedStatement ps = sqlControl.getStatementForQuery(conn, queryStmt, rsTypeString, rsConcurrencyString); return ps; }
/** * Convenience logging method to output the mapping information for an element, key, value field * * @param mapping The mapping */ protected void debugMapping(JavaTypeMapping mapping) { if (NucleusLogger.DATASTORE.isDebugEnabled()) { // Provide field->column mapping debug message StringBuffer columnsStr = new StringBuffer(); for (int i = 0; i < mapping.getNumberOfDatastoreMappings(); i++) { if (i > 0) { columnsStr.append(","); } columnsStr.append(mapping.getDatastoreMapping(i).getDatastoreField()); } if (mapping.getNumberOfDatastoreMappings() == 0) { columnsStr.append("[none]"); } StringBuffer datastoreMappingTypes = new StringBuffer(); for (int i = 0; i < mapping.getNumberOfDatastoreMappings(); i++) { if (i > 0) { datastoreMappingTypes.append(','); } datastoreMappingTypes.append(mapping.getDatastoreMapping(i).getClass().getName()); } NucleusLogger.DATASTORE.debug( LOCALISER.msg( "057010", mmd.getFullFieldName(), columnsStr.toString(), mapping.getClass().getName(), datastoreMappingTypes.toString())); } }
public VersionMetaData setStrategy(String strategy) { if (StringUtils.isWhitespace(strategy) || VersionStrategy.getVersionStrategy(strategy) == null) { throw new RuntimeException(LOCALISER.msg("044156")); } this.versionStrategy = VersionStrategy.getVersionStrategy(strategy); return this; }
/* (non-Javadoc) * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List) */ public SQLExpression getExpression(SQLExpression expr, List args) { if (expr != null) { throw new NucleusException(LOCALISER.msg("060002", getFunctionName(), expr)); } else if (args == null || args.size() != 1) { throw new NucleusException(getFunctionName() + " is only supported with a single argument"); } if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) { // FUNC(argExpr) JavaTypeMapping m = null; if (args.get(0) instanceof SQLExpression) { // Use same java type as the argument SQLExpression argExpr = (SQLExpression) args.get(0); m = getMappingForClass(argExpr.getJavaTypeMapping().getJavaType()); if (args.get(0) instanceof TemporalExpression) { return new AggregateTemporalExpression(stmt, m, getFunctionName(), args); } else { return new AggregateNumericExpression(stmt, m, getFunctionName(), args); } } else { // What is coming through here? // Fallback to the type for this aggregate TODO Allow for temporal types m = getMappingForClass(double.class); return new AggregateNumericExpression(stmt, m, getFunctionName(), args); } } else { // Handle as Subquery "SELECT AVG(expr) FROM tbl" SQLExpression argExpr = (SQLExpression) args.get(0); SQLStatement subStmt = new SQLStatement( stmt, stmt.getRDBMSManager(), argExpr.getSQLTable().getTable(), argExpr.getSQLTable().getAlias(), null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping mapping = stmt.getRDBMSManager() .getMappingManager() .getMappingWithDatastoreMapping(String.class, false, false, clr); String aggregateString = getFunctionName() + "(" + argExpr.toSQLText() + ")"; SQLExpression aggExpr = exprFactory.newLiteral(subStmt, mapping, aggregateString); ((StringLiteral) aggExpr).generateStatementWithoutQuotes(); subStmt.select(aggExpr, null); JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false); SQLExpression subqExpr = null; if (argExpr instanceof TemporalExpression) { subqExpr = new TemporalSubqueryExpression(stmt, subStmt); } else { subqExpr = new NumericSubqueryExpression(stmt, subStmt); } subqExpr.setJavaTypeMapping(subqMapping); return subqExpr; } }
/* (non-Javadoc) * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List) */ public SQLExpression getExpression(SQLExpression expr, List args) { if (!(expr instanceof TemporalExpression)) { throw new NucleusException(LOCALISER.msg("060001", "getSecond()", expr)); } ArrayList funcArgs = new ArrayList(); funcArgs.add(expr); return new NumericExpression(stmt, getMappingForClass(int.class), "SECOND", funcArgs); }
/** * Method to apply any restrictions to the created ResultSet. * * @param ps The PreparedStatement * @param query The query * @param applyTimeout Whether to apply the query timeout (if any) direct to the PreparedStatement * @throws SQLException Thrown when an error occurs applying the constraints */ public static void prepareStatementForExecution( PreparedStatement ps, Query query, boolean applyTimeout) throws SQLException { NucleusContext nucleusCtx = query.getExecutionContext().getNucleusContext(); RDBMSStoreManager storeMgr = (RDBMSStoreManager) query.getStoreManager(); PersistenceConfiguration conf = nucleusCtx.getPersistenceConfiguration(); if (applyTimeout) { Integer timeout = query.getDatastoreReadTimeoutMillis(); if (timeout != null && timeout > 0) { ps.setQueryTimeout(timeout / 1000); } } // Apply any fetch size int fetchSize = 0; if (query.getFetchPlan().getFetchSize() > 0) { // FetchPlan has a size set so use that fetchSize = query.getFetchPlan().getFetchSize(); } if (storeMgr.getDatastoreAdapter().supportsQueryFetchSize(fetchSize)) { ps.setFetchSize(fetchSize); } // Apply any fetch direction String fetchDir = conf.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_FETCH_DIRECTION); Object fetchDirExt = query.getExtension(RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_FETCH_DIRECTION); if (fetchDirExt != null) { fetchDir = (String) fetchDirExt; if (!fetchDir.equals("forward") && !fetchDir.equals("reverse") && !fetchDir.equals("unknown")) { throw new NucleusUserException(LOCALISER.msg("052512")); } } if (fetchDir.equals("reverse")) { ps.setFetchDirection(ResultSet.FETCH_REVERSE); } else if (fetchDir.equals("unknown")) { ps.setFetchDirection(ResultSet.FETCH_UNKNOWN); } // Add a limit on the number of rows to include the maximum we may need long toExclNo = query.getRangeToExcl(); if (toExclNo != 0 && toExclNo != Long.MAX_VALUE) { if (toExclNo > Integer.MAX_VALUE) { // setMaxRows takes an int as input so limit to the correct range ps.setMaxRows(Integer.MAX_VALUE); } else { ps.setMaxRows((int) toExclNo); } } }
/** * Constructor. * * @param tableName The Table SQL identifier * @param mmd Field meta data for the owner field/property * @param storeMgr Manager for the datastore. */ protected JoinTable( DatastoreIdentifier tableName, AbstractMemberMetaData mmd, RDBMSStoreManager storeMgr) { super(tableName, storeMgr); this.mmd = mmd; this.ownerType = mmd.getClassName(true); if (mmd.getPersistenceModifier() == FieldPersistenceModifier.NONE) { throw new NucleusException(LOCALISER.msg("057006", mmd.getName())).setFatal(); } }
/** * Method to add an element to the TreeSet. * * @param element The new element * @return Whether it was added ok. */ public boolean add(Object element) { // Reject inappropriate elements if (!allowNulls && element == null) { throw new NullPointerException( "Nulls not allowed for collection at field " + ownerMmd.getName() + " but element is null"); } if (useCache) { loadFromStore(); } if (contains(element)) { return false; } if (ownerOP != null && ownerOP.getExecutionContext().getManageRelations()) { // Relationship management ownerOP .getExecutionContext() .getRelationshipManager(ownerOP) .relationAdd(ownerMmd.getAbsoluteFieldNumber(), element); } boolean backingSuccess = true; if (backingStore != null) { if (SCOUtils.useQueuedUpdate(queued, ownerOP)) { ownerOP .getExecutionContext() .addOperationToQueue(new CollectionAddOperation(ownerOP, backingStore, element)); } else { try { backingStore.add(ownerOP, element, (useCache ? delegate.size() : -1)); } catch (NucleusDataStoreException dse) { NucleusLogger.PERSISTENCE.warn(LOCALISER.msg("023013", "add", ownerMmd.getName(), dse)); backingSuccess = false; } } } // Only make it dirty after adding the field to the datastore so we give it time // to be inserted - otherwise jdoPreStore on this object would have been called before // completing the addition makeDirty(); boolean delegateSuccess = delegate.add(element); if (ownerOP != null && !ownerOP.getExecutionContext().getTransaction().isActive()) { ownerOP.getExecutionContext().processNontransactionalUpdate(); } return (backingStore != null ? backingSuccess : delegateSuccess); }
/** * Convenience method to apply the user specification of <primary-key> columns * * @param pkmd MetaData for the primary key */ protected void applyUserPrimaryKeySpecification(PrimaryKeyMetaData pkmd) { ColumnMetaData[] pkCols = pkmd.getColumnMetaData(); for (int i = 0; i < pkCols.length; i++) { String colName = pkCols[i].getName(); boolean found = false; for (int j = 0; j < ownerMapping.getNumberOfDatastoreMappings(); j++) { if (ownerMapping .getDatastoreMapping(j) .getDatastoreField() .getIdentifier() .getIdentifierName() .equals(colName)) { ownerMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey(); found = true; } } if (!found) { for (int j = 0; j < keyMapping.getNumberOfDatastoreMappings(); j++) { if (keyMapping .getDatastoreMapping(j) .getDatastoreField() .getIdentifier() .getIdentifierName() .equals(colName)) { keyMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey(); found = true; } } } if (!found) { for (int j = 0; j < valueMapping.getNumberOfDatastoreMappings(); j++) { if (valueMapping .getDatastoreMapping(j) .getDatastoreField() .getIdentifier() .getIdentifierName() .equals(colName)) { valueMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey(); found = true; } } } if (!found) { throw new NucleusUserException(LOCALISER.msg("057040", toString(), colName)); } } }
/** Method to load all elements from the "backing store" where appropriate. */ protected void loadFromStore() { if (backingStore != null && !isCacheLoaded) { if (NucleusLogger.PERSISTENCE.isDebugEnabled()) { NucleusLogger.PERSISTENCE.debug( LOCALISER.msg("023006", ownerOP.getObjectAsPrintable(), ownerMmd.getName())); } delegate.clear(); Iterator iter = backingStore.iterator(ownerOP); while (iter.hasNext()) { delegate.add(iter.next()); } isCacheLoaded = true; } }
/** * Method to remove an element from the collection, and observe the flag for whether to allow * cascade delete. * * @param element The element * @param allowCascadeDelete Whether to allow cascade delete */ public boolean remove(Object element, boolean allowCascadeDelete) { makeDirty(); if (useCache) { loadFromStore(); } int size = (useCache ? delegate.size() : -1); boolean contained = delegate.contains(element); boolean delegateSuccess = delegate.remove(element); if (ownerOP != null && ownerOP.getExecutionContext().getManageRelations()) { ownerOP .getExecutionContext() .getRelationshipManager(ownerOP) .relationRemove(ownerMmd.getAbsoluteFieldNumber(), element); } boolean backingSuccess = true; if (backingStore != null) { if (SCOUtils.useQueuedUpdate(queued, ownerOP)) { backingSuccess = contained; if (backingSuccess) { ownerOP .getExecutionContext() .addOperationToQueue( new CollectionRemoveOperation( ownerOP, backingStore, element, allowCascadeDelete)); } } else { try { backingSuccess = backingStore.remove(ownerOP, element, size, allowCascadeDelete); } catch (NucleusDataStoreException dse) { NucleusLogger.PERSISTENCE.warn( LOCALISER.msg("023013", "remove", ownerMmd.getName(), dse)); backingSuccess = false; } } } if (ownerOP != null && !ownerOP.getExecutionContext().getTransaction().isActive()) { ownerOP.getExecutionContext().processNontransactionalUpdate(); } return (backingStore != null ? backingSuccess : delegateSuccess); }
/** * Method to add a collection to the TreeSet. * * @param elements The collection * @return Whether it was added ok. */ public boolean addAll(Collection elements) { if (useCache) { loadFromStore(); } if (ownerOP != null && ownerOP.getExecutionContext().getManageRelations()) { // Relationship management Iterator iter = elements.iterator(); RelationshipManager relMgr = ownerOP.getExecutionContext().getRelationshipManager(ownerOP); while (iter.hasNext()) { relMgr.relationAdd(ownerMmd.getAbsoluteFieldNumber(), iter.next()); } } boolean backingSuccess = true; if (backingStore != null) { if (SCOUtils.useQueuedUpdate(queued, ownerOP)) { for (Object element : elements) { ownerOP .getExecutionContext() .addOperationToQueue(new CollectionAddOperation(ownerOP, backingStore, element)); } } else { try { backingSuccess = backingStore.addAll(ownerOP, elements, (useCache ? delegate.size() : -1)); } catch (NucleusDataStoreException dse) { NucleusLogger.PERSISTENCE.warn( LOCALISER.msg("023013", "addAll", ownerMmd.getName(), dse)); backingSuccess = false; } } } // Only make it dirty after adding the field to the datastore so we give it time // to be inserted - otherwise jdoPreStore on this object would have been called before // completing the addition makeDirty(); boolean delegateSuccess = delegate.addAll(elements); if (ownerOP != null && !ownerOP.getExecutionContext().getTransaction().isActive()) { ownerOP.getExecutionContext().processNontransactionalUpdate(); } return (backingStore != null ? backingSuccess : delegateSuccess); }
/** * Method to create the repository for ids to be stored. * * @return Whether it was created successfully. */ protected boolean createRepository() { RDBMSStoreManager srm = (RDBMSStoreManager) storeMgr; if (!srm.isAutoCreateTables()) { throw new NucleusUserException(LOCALISER.msg("040011", sequenceTable)); } try { if (sequenceTable == null) { initialiseSequenceTable(); } sequenceTable.exists((Connection) connection.getConnection(), true); repositoryExists = true; return true; } catch (SQLException sqle) { throw new ValueGenerationException( "Exception thrown calling table.exists() for " + sequenceTable, sqle); } }
public BitSet toMemberType(String str) { if (str == null) { return null; } BitSet set = new BitSet(); StringTokenizer tokeniser = new StringTokenizer(str.substring(1, str.length() - 1), ","); while (tokeniser.hasMoreTokens()) { String token = tokeniser.nextToken().trim(); try { int position = new Integer(token).intValue(); set.set(position); } catch (NumberFormatException nfe) { throw new NucleusDataStoreException( LOCALISER.msg("016002", str, BitSet.class.getName()), nfe); } } return set; }
/** * Method to reserve a block of "size" identities. * * @param size Block size * @return The reserved block */ public ValueGenerationBlock reserveBlock(long size) { if (size < 1) { return null; } // search for an ID in the database List oid = new ArrayList(); try { if (sequenceTable == null) { initialiseSequenceTable(); } DatastoreIdentifier sourceTableIdentifier = null; if (properties.getProperty("table-name") != null) { sourceTableIdentifier = ((RDBMSStoreManager) storeMgr) .getIdentifierFactory() .newTableIdentifier(properties.getProperty("table-name")); // TODO Apply passed in catalog/schema to this identifier rather than the default for the // factory } Long nextId = sequenceTable.getNextVal( sequenceName, connection, (int) size, sourceTableIdentifier, properties.getProperty("column-name"), initialValue); for (int i = 0; i < size; i++) { oid.add(nextId); nextId = Long.valueOf(nextId.longValue() + 1); } if (NucleusLogger.VALUEGENERATION.isDebugEnabled()) { NucleusLogger.VALUEGENERATION.debug(LOCALISER.msg("040004", "" + size)); } return new ValueGenerationBlock(oid); } catch (SQLException e) { throw new ValueGenerationException(LOCALISER_RDBMS.msg("061001", e.getMessage())); } }
/** * Constructor. * * @param name Symbolic name for this generator * @param props Properties defining the behaviour of this generator */ public TableGenerator(String name, Properties props) { super(name, props); allocationSize = 5; initialValue = -1; // So we know if being set if (properties != null) { if (properties.get("key-cache-size") != null) { try { allocationSize = Integer.parseInt(properties.getProperty("key-cache-size")); } catch (Exception e) { throw new ValueGenerationException( LOCALISER.msg("Sequence040006", properties.get("key-cache-size"))); } } if (properties.get("key-initial-value") != null) { try { initialValue = Integer.parseInt(properties.getProperty("key-initial-value")); } catch (NumberFormatException nfe) { // Not an integer so ignore it } } if (properties.getProperty("sequence-name") != null) { // Specified sequence-name so use that sequenceName = properties.getProperty("sequence-name"); } else if (properties.getProperty("sequence-table-basis") != null && properties.getProperty("sequence-table-basis").equalsIgnoreCase("table")) { // Use table name in the sequence table as the sequence name sequenceName = properties.getProperty("table-name"); } else { // Use root class name (for this inheritance tree) in the sequence table as the sequence // name sequenceName = properties.getProperty("root-class-name"); } } else { // User hasn't provided any sequence name!!! sequenceName = "SEQUENCENAME"; } }
/** * Method to populate any defaults, and check the validity of the MetaData. * * @param clr ClassLoaderResolver to use for any loading operations * @param primary the primary ClassLoader to use (or null) * @param mmgr MetaData manager */ public void populate(ClassLoaderResolver clr, ClassLoader primary, MetaDataManager mmgr) { AbstractMemberMetaData mmd = (AbstractMemberMetaData) parent; if (!StringUtils.isWhitespace(element.type) && element.type.indexOf(',') > 0) { throw new InvalidMetaDataException(LOCALISER, "044131", mmd.getName(), mmd.getClassName()); } // Make sure the type in "element" is set element.populate( ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(), clr, primary, mmgr); // Check the field type and see if it is castable to a Collection Class field_type = getMemberMetaData().getType(); if (!java.util.Collection.class.isAssignableFrom(field_type)) { throw new InvalidMetaDataException( LOCALISER, "044132", getFieldName(), getMemberMetaData().getClassName(false)); } // "element-type" if (element.type == null) { throw new InvalidMetaDataException( LOCALISER, "044133", getFieldName(), getMemberMetaData().getClassName(false)); } // Check that the element type exists Class elementTypeClass = null; try { elementTypeClass = clr.classForName(element.type, primary); } catch (ClassNotResolvedException cnre) { throw new InvalidMetaDataException( LOCALISER, "044134", getFieldName(), getMemberMetaData().getClassName(false), element.type); } if (!elementTypeClass.getName().equals(element.type)) { // The element-type has been resolved from what was specified in the MetaData - update to the // fully-qualified name NucleusLogger.METADATA.info( LOCALISER.msg( "044135", getFieldName(), getMemberMetaData().getClassName(false), element.type, elementTypeClass.getName())); element.type = elementTypeClass.getName(); } // "embedded-element" ApiAdapter api = mmgr.getApiAdapter(); if (element.embedded == null) { // Assign default for "embedded-element" based on 18.13.1 of JDO 2 spec // Note : this fails when using in the enhancer since not yet PC if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(elementTypeClass)) { element.embedded = Boolean.TRUE; } else if (api.isPersistable(elementTypeClass) || Object.class.isAssignableFrom(elementTypeClass) || elementTypeClass.isInterface()) { element.embedded = Boolean.FALSE; } else { element.embedded = Boolean.TRUE; } } if (Boolean.FALSE.equals(element.embedded)) { // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported. // Note : this fails when using in the enhancer since not yet PC if (!api.isPersistable(elementTypeClass) && !elementTypeClass.isInterface() && elementTypeClass != java.lang.Object.class) { element.embedded = Boolean.TRUE; } } ElementMetaData elemmd = ((AbstractMemberMetaData) parent).getElementMetaData(); if (elemmd != null && elemmd.getEmbeddedMetaData() != null) { element.embedded = Boolean.TRUE; } if (Boolean.TRUE.equals(element.dependent)) { // If the user has set a non-PC/non-reference as dependent, correct it since not valid. // Note : this fails when using in the enhancer since not yet PC if (!api.isPersistable(elementTypeClass) && !elementTypeClass.isInterface() && elementTypeClass != java.lang.Object.class) { element.dependent = Boolean.FALSE; } } // Keep a reference to the MetaData for the element element.classMetaData = mmgr.getMetaDataForClassInternal(elementTypeClass, clr); // Make sure anything in the superclass is populated too super.populate(clr, primary, mmgr); setPopulated(); }
/** * Method to populate any defaults, and check the validity of the MetaData. * * @param clr ClassLoaderResolver to use for loading any key/value types * @param primary the primary ClassLoader to use (or null) * @param mmgr MetaData manager */ public void populate(ClassLoaderResolver clr, ClassLoader primary, MetaDataManager mmgr) { AbstractMemberMetaData mmd = (AbstractMemberMetaData) parent; if (!StringUtils.isWhitespace(key.type) && key.type.indexOf(',') > 0) { throw new InvalidMetaDataException(LOCALISER, "044143", mmd.getName(), mmd.getClassName()); } if (!StringUtils.isWhitespace(value.type) && value.type.indexOf(',') > 0) { throw new InvalidMetaDataException(LOCALISER, "044144", mmd.getName(), mmd.getClassName()); } ApiAdapter api = mmgr.getApiAdapter(); // Make sure the type in "key", "value" is set key.populate( ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(), clr, primary, mmgr); value.populate( ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(), clr, primary, mmgr); // Check the field type and see if it is castable to a Map Class field_type = getMemberMetaData().getType(); if (!java.util.Map.class.isAssignableFrom(field_type)) { throw new InvalidMetaDataException( LOCALISER, "044145", getFieldName(), getMemberMetaData().getClassName(false)); } if (java.util.Properties.class.isAssignableFrom(field_type)) { // Properties defaults to <String, String> if (key.type == null) { key.type = String.class.getName(); } if (value.type == null) { value.type = String.class.getName(); } } // "key-type" if (key.type == null) { throw new InvalidMetaDataException( LOCALISER, "044146", getFieldName(), getMemberMetaData().getClassName(false)); } // Check that the key type exists Class keyTypeClass = null; try { keyTypeClass = clr.classForName(key.type, primary); } catch (ClassNotResolvedException cnre) { try { // Maybe the user specified a java.lang class without fully-qualifying it // This is beyond the scope of the JDO spec which expects java.lang cases to be // fully-qualified keyTypeClass = clr.classForName(ClassUtils.getJavaLangClassForType(key.type), primary); } catch (ClassNotResolvedException cnre2) { throw new InvalidMetaDataException( LOCALISER, "044147", getFieldName(), getMemberMetaData().getClassName(false), key.type); } } if (!keyTypeClass.getName().equals(key.type)) { // The value-type has been resolved from what was specified in the MetaData - update to the // fully-qualified name NucleusLogger.METADATA.info( LOCALISER.msg( "044148", getFieldName(), getMemberMetaData().getClassName(false), key.type, keyTypeClass.getName())); key.type = keyTypeClass.getName(); } // "embedded-key" if (key.embedded == null) { // Assign default for "embedded-key" based on 18.13.2 of JDO 2 spec if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(keyTypeClass)) { key.embedded = Boolean.TRUE; } else if (api.isPersistable(keyTypeClass) || Object.class.isAssignableFrom(keyTypeClass) || keyTypeClass.isInterface()) { key.embedded = Boolean.FALSE; } else { key.embedded = Boolean.TRUE; } } if (Boolean.FALSE.equals(key.embedded)) { // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported. // Note : this fails when using in the enhancer since not yet PC if (!api.isPersistable(keyTypeClass) && !keyTypeClass.isInterface() && keyTypeClass != java.lang.Object.class) { key.embedded = Boolean.TRUE; } } KeyMetaData keymd = ((AbstractMemberMetaData) parent).getKeyMetaData(); if (keymd != null && keymd.getEmbeddedMetaData() != null) { // If the user has specified <embedded>, set to true key.embedded = Boolean.TRUE; } // "value-type" if (value.type == null) { throw new InvalidMetaDataException( LOCALISER, "044149", getFieldName(), getMemberMetaData().getClassName(false)); } // Check that the value-type exists Class valueTypeClass = null; try { valueTypeClass = clr.classForName(value.type); } catch (ClassNotResolvedException cnre) { try { // Maybe the user specified a java.lang class without fully-qualifying it // This is beyond the scope of the JDO spec which expects java.lang cases to be // fully-qualified valueTypeClass = clr.classForName(ClassUtils.getJavaLangClassForType(value.type)); } catch (ClassNotResolvedException cnre2) { throw new InvalidMetaDataException( LOCALISER, "044150", getFieldName(), getMemberMetaData().getClassName(false), value.type); } } if (!valueTypeClass.getName().equals(value.type)) { // The value-type has been resolved from what was specified in the MetaData - update to the // fully-qualified name NucleusLogger.METADATA.info( LOCALISER.msg( "044151", getFieldName(), getMemberMetaData().getClassName(false), value.type, valueTypeClass.getName())); value.type = valueTypeClass.getName(); } // "embedded-value" if (value.embedded == null) { // Assign default for "embedded-value" based on 18.13.2 of JDO 2 spec if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(valueTypeClass)) { value.embedded = Boolean.TRUE; } else if (api.isPersistable(valueTypeClass) || Object.class.isAssignableFrom(valueTypeClass) || valueTypeClass.isInterface()) { value.embedded = Boolean.FALSE; } else { value.embedded = Boolean.TRUE; } } if (value.embedded == Boolean.FALSE) { // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported. // Note : this fails when using in the enhancer since not yet PC if (!api.isPersistable(valueTypeClass) && !valueTypeClass.isInterface() && valueTypeClass != java.lang.Object.class) { value.embedded = Boolean.TRUE; } } ValueMetaData valuemd = ((AbstractMemberMetaData) parent).getValueMetaData(); if (valuemd != null && valuemd.getEmbeddedMetaData() != null) { // If the user has specified <embedded>, set to true value.embedded = Boolean.TRUE; } key.classMetaData = mmgr.getMetaDataForClassInternal(keyTypeClass, clr); value.classMetaData = mmgr.getMetaDataForClassInternal(valueTypeClass, clr); // Cater for Key with mapped-by needing to be PK (for JPA) if (keymd != null && keymd.mappedBy != null && keymd.mappedBy.equals("#PK")) // Special value set by JPAMetaDataHandler { // Need to set the mapped-by of <key> to be the PK of the <value> if (value.classMetaData.getNoOfPrimaryKeyMembers() != 1) { // TODO Localise this throw new NucleusUserException( "DataNucleus does not support use of <map-key> with no name field when the" + " value class has a composite primary key"); } int[] valuePkFieldNums = value.classMetaData.getPKMemberPositions(); keymd.mappedBy = value.classMetaData.getMetaDataForManagedMemberAtAbsolutePosition(valuePkFieldNums[0]) .name; } // Make sure anything in the superclass is populated too super.populate(clr, primary, mmgr); setPopulated(); }
/** * Method to remove all elements from the collection from the TreeSet. * * @param elements The collection of elements to remove * @return Whether it was removed ok. */ public boolean removeAll(java.util.Collection elements) { makeDirty(); if (useCache) { loadFromStore(); } int size = (useCache ? delegate.size() : -1); Collection contained = null; if (backingStore != null && SCOUtils.useQueuedUpdate(queued, ownerOP)) { // Check which are contained before updating the delegate contained = new java.util.HashSet(); for (Object elem : elements) { if (contains(elem)) { contained.add(elem); } } } boolean delegateSuccess = delegate.removeAll(elements); if (ownerOP != null && ownerOP.getExecutionContext().getManageRelations()) { // Relationship management Iterator iter = elements.iterator(); RelationshipManager relMgr = ownerOP.getExecutionContext().getRelationshipManager(ownerOP); while (iter.hasNext()) { relMgr.relationRemove(ownerMmd.getAbsoluteFieldNumber(), iter.next()); } } if (backingStore != null) { boolean backingSuccess = true; if (SCOUtils.useQueuedUpdate(queued, ownerOP)) { backingSuccess = false; for (Object element : contained) { backingSuccess = true; ownerOP .getExecutionContext() .addOperationToQueue( new CollectionRemoveOperation(ownerOP, backingStore, element, true)); } } else { try { backingSuccess = backingStore.removeAll(ownerOP, elements, size); } catch (NucleusDataStoreException dse) { NucleusLogger.PERSISTENCE.warn( LOCALISER.msg("023013", "removeAll", ownerMmd.getName(), dse)); backingSuccess = false; } } if (ownerOP != null && !ownerOP.getExecutionContext().getTransaction().isActive()) { ownerOP.getExecutionContext().processNontransactionalUpdate(); } return backingSuccess; } else { if (ownerOP != null && !ownerOP.getExecutionContext().getTransaction().isActive()) { ownerOP.getExecutionContext().processNontransactionalUpdate(); } return delegateSuccess; } }
/** * Method to initialise the table definition. * * @param clr The ClassLoaderResolver */ public void initialize(ClassLoaderResolver clr) { assertIsUninitialized(); MapMetaData mapmd = mmd.getMap(); if (mapmd == null) { throw new NucleusUserException(LOCALISER.msg("057017", mmd)); } PrimaryKeyMetaData pkmd = (mmd.getJoinMetaData() != null ? mmd.getJoinMetaData().getPrimaryKeyMetaData() : null); boolean pkColsSpecified = (pkmd != null && pkmd.getColumnMetaData() != null); boolean pkRequired = requiresPrimaryKey(); // Add owner mapping ColumnMetaData[] ownerColmd = null; if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getColumnMetaData() != null && mmd.getJoinMetaData().getColumnMetaData().length > 0) { // Column mappings defined at this side (1-N, M-N) // When specified at this side they use the <join> tag ownerColmd = mmd.getJoinMetaData().getColumnMetaData(); } ownerMapping = ColumnCreator.createColumnsForJoinTables( clr.classForName(ownerType), mmd, ownerColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_OWNER, clr); if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(ownerMapping); } String keyValueFieldName = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getMappedBy() : null); String valueKeyFieldName = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getMappedBy() : null); // Add key mapping boolean keyPC = (mmd.hasMap() && mmd.getMap().keyIsPersistent()); Class keyCls = clr.classForName(mapmd.getKeyType()); if (keyValueFieldName != null && isEmbeddedValuePC()) { // Added in value code } else if (isSerialisedKey() || isEmbeddedKeyPC() || (isEmbeddedKey() && !keyPC) || ClassUtils.isReferenceType(keyCls)) { // Key = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference keyMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_KEY); if (Boolean.TRUE.equals(mmd.getContainer().allowNulls())) { // Make all key col(s) nullable so we can store null elements for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) { Column elementCol = (Column) keyMapping.getDatastoreMapping(i).getDatastoreField(); elementCol.setNullable(); } } if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(keyMapping); } if (valueKeyFieldName != null && isEmbeddedKeyPC()) { // Key (PC) is embedded and value is a field of the key EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping; valueMapping = embMapping.getJavaTypeMapping(valueKeyFieldName); } } else { // Key = PC ColumnMetaData[] keyColmd = null; KeyMetaData keymd = mmd.getKeyMetaData(); if (keymd != null && keymd.getColumnMetaData() != null && keymd.getColumnMetaData().length > 0) { // Column mappings defined at this side (1-N, M-N) keyColmd = keymd.getColumnMetaData(); } keyMapping = ColumnCreator.createColumnsForJoinTables( keyCls, mmd, keyColmd, storeMgr, this, false, false, FieldRole.ROLE_MAP_KEY, clr); if (mmd.getContainer().allowNulls() == Boolean.TRUE) { // Make all key col(s) nullable so we can store null elements for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) { Column elementCol = (Column) keyMapping.getDatastoreMapping(i).getDatastoreField(); elementCol.setNullable(); } } if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(keyMapping); } } // Add value mapping boolean valuePC = (mmd.hasMap() && mmd.getMap().valueIsPersistent()); Class valueCls = clr.classForName(mapmd.getValueType()); if (valueKeyFieldName != null && isEmbeddedKeyPC()) { // Added in key code } else if (isSerialisedValue() || isEmbeddedValuePC() || (isEmbeddedValue() && !valuePC) || ClassUtils.isReferenceType(valueCls)) { // Value = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference valueMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_VALUE); if (mmd.getContainer().allowNulls() == Boolean.TRUE) { // Make all value col(s) nullable so we can store null elements for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) { Column elementCol = (Column) valueMapping.getDatastoreMapping(i).getDatastoreField(); elementCol.setNullable(); } } if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(valueMapping); } if (keyValueFieldName != null && isEmbeddedValuePC()) { // Value (PC) is embedded and key is a field of the value EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping; keyMapping = embMapping.getJavaTypeMapping(keyValueFieldName); } } else { // Value = PC ColumnMetaData[] valueColmd = null; ValueMetaData valuemd = mmd.getValueMetaData(); if (valuemd != null && valuemd.getColumnMetaData() != null && valuemd.getColumnMetaData().length > 0) { // Column mappings defined at this side (1-N, M-N) valueColmd = valuemd.getColumnMetaData(); } valueMapping = ColumnCreator.createColumnsForJoinTables( clr.classForName(mapmd.getValueType()), mmd, valueColmd, storeMgr, this, false, true, FieldRole.ROLE_MAP_VALUE, clr); if (mmd.getContainer().allowNulls() == Boolean.TRUE) { // Make all value col(s) nullable so we can store null elements for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) { Column elementCol = (Column) valueMapping.getDatastoreMapping(i).getDatastoreField(); elementCol.setNullable(); } } if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(valueMapping); } } // Add order mapping if required boolean orderRequired = false; if (mmd.getOrderMetaData() != null) { // User requested order column so add one orderRequired = true; } else if (requiresPrimaryKey() && !pkColsSpecified) { // PK is required so maybe need to add an index to form the PK if (isEmbeddedKeyPC()) { if (mmd.getMap().getKeyClassMetaData(clr, storeMgr.getMetaDataManager()).getIdentityType() != IdentityType.APPLICATION) { // Embedded key PC with datastore id so we need an index to form the PK orderRequired = true; } } else if (isSerialisedKey()) { // Serialised key, so need an index to form the PK orderRequired = true; } else if (keyMapping instanceof ReferenceMapping) { // ReferenceMapping, so have order if more than 1 implementation ReferenceMapping refMapping = (ReferenceMapping) keyMapping; if (refMapping.getJavaTypeMapping().length > 1) { orderRequired = true; } } else if (!(keyMapping instanceof PersistableMapping)) { // Non-PC, so depends if the key column can be used as part of a PK // TODO This assumes the keyMapping has a single column but what if it is Color with 4 cols? Column elementCol = (Column) keyMapping.getDatastoreMapping(0).getDatastoreField(); if (!((RDBMSAdapter) storeMgr.getDatastoreAdapter()) .isValidPrimaryKeyType(elementCol.getJdbcType())) { // Not possible to use this Non-PC type as part of the PK orderRequired = true; } } } if (orderRequired) { // Order/Adapter (index) column is required (integer based) ColumnMetaData orderColmd = null; if (mmd.getOrderMetaData() != null && mmd.getOrderMetaData().getColumnMetaData() != null && mmd.getOrderMetaData().getColumnMetaData().length > 0) { // Specified "order" column info orderColmd = mmd.getOrderMetaData().getColumnMetaData()[0]; if (orderColmd.getName() == null) { orderColmd = new ColumnMetaData(orderColmd); if (mmd.hasExtension("adapter-column-name")) { // Specified "extension" column name // TODO Is this needed? The user can just specify <order column="..."> orderColmd.setName(mmd.getValueForExtension("adapter-column-name")); } else { // No column name so use default DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd); orderColmd.setName(id.getIdentifierName()); } } } else { if (mmd.hasExtension("adapter-column-name")) { // Specified "extension" column name // TODO Is this needed? The user can just specify <order column="..."> orderColmd = new ColumnMetaData(); orderColmd.setName(mmd.getValueForExtension("adapter-column-name")); } else { // No column name so use default DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd); orderColmd = new ColumnMetaData(); orderColmd.setName(id.getIdentifierName()); } } orderMapping = storeMgr .getMappingManager() .getMapping(int.class); // JDO2 spec [18.5] order column is assumed to be "int" ColumnCreator.createIndexColumn( orderMapping, storeMgr, clr, this, orderColmd, pkRequired && !pkColsSpecified); if (NucleusLogger.DATASTORE.isDebugEnabled()) { debugMapping(orderMapping); } } // Define primary key of the join table (if any) if (pkRequired) { if (pkColsSpecified) { // Apply the users PK specification applyUserPrimaryKeySpecification(pkmd); } else { // Define PK using JPOX rules if (orderRequired) { // Order column specified so owner+order are the PK orderMapping.getDatastoreMapping(0).getDatastoreField().setAsPrimaryKey(); } else { // No order column specified so owner+key are the PK for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) { keyMapping.getDatastoreMapping(i).getDatastoreField().setAsPrimaryKey(); } } } } state = TABLE_STATE_INITIALIZED; }
/** * Method to initialise the SCO from an existing value. * * @param o The object to set from * @param forInsert Whether the object needs inserting in the datastore with this value * @param forUpdate Whether to update the datastore with this value */ public void initialise(Object o, boolean forInsert, boolean forUpdate) { Collection c = (Collection) o; if (c != null) { // Check for the case of serialised PC elements, and assign ObjectProviders to the elements // without if (SCOUtils.collectionHasSerialisedElements(ownerMmd) && ownerMmd.getCollection().elementIsPersistent()) { ExecutionContext ec = ownerOP.getExecutionContext(); Iterator iter = c.iterator(); while (iter.hasNext()) { Object pc = iter.next(); ObjectProvider objSM = ec.findObjectProvider(pc); if (objSM == null) { objSM = ec.newObjectProviderForEmbedded( pc, false, ownerOP, ownerMmd.getAbsoluteFieldNumber()); } } } if (backingStore != null && useCache && !isCacheLoaded) { // Mark as loaded isCacheLoaded = true; } if (forInsert) { if (NucleusLogger.PERSISTENCE.isDebugEnabled()) { NucleusLogger.PERSISTENCE.debug( LOCALISER.msg( "023007", ownerOP.getObjectAsPrintable(), ownerMmd.getName(), "" + c.size())); } if (useCache) { loadFromStore(); } if (ownerOP != null && ownerOP.getExecutionContext().getManageRelations()) { // Relationship management Iterator iter = c.iterator(); RelationshipManager relMgr = ownerOP.getExecutionContext().getRelationshipManager(ownerOP); while (iter.hasNext()) { relMgr.relationAdd(ownerMmd.getAbsoluteFieldNumber(), iter.next()); } } if (backingStore != null) { if (SCOUtils.useQueuedUpdate(queued, ownerOP)) { for (Object element : c) { ownerOP .getExecutionContext() .addOperationToQueue(new CollectionAddOperation(ownerOP, backingStore, element)); } } else { try { backingStore.addAll(ownerOP, c, (useCache ? delegate.size() : -1)); } catch (NucleusDataStoreException dse) { NucleusLogger.PERSISTENCE.warn( LOCALISER.msg("023013", "addAll", ownerMmd.getName(), dse)); } } } delegate.addAll(c); makeDirty(); } else if (forUpdate) { if (NucleusLogger.PERSISTENCE.isDebugEnabled()) { NucleusLogger.PERSISTENCE.debug( LOCALISER.msg( "023008", ownerOP.getObjectAsPrintable(), ownerMmd.getName(), "" + c.size())); } // Detect which objects are added and which are deleted if (useCache) { isCacheLoaded = false; // Mark as false since need to load the old collection loadFromStore(); for (Object elem : c) { if (!delegate.contains(elem)) { add(elem); } } java.util.TreeSet delegateCopy = new java.util.TreeSet(delegate); for (Object elem : delegateCopy) { if (!c.contains(elem)) { remove(elem); } } } else { for (Object elem : c) { if (!contains(elem)) { add(elem); } } Iterator iter = iterator(); while (iter.hasNext()) { Object elem = iter.next(); if (!c.contains(elem)) { remove(elem); } } } } else { if (NucleusLogger.PERSISTENCE.isDebugEnabled()) { NucleusLogger.PERSISTENCE.debug( LOCALISER.msg( "023007", ownerOP.getObjectAsPrintable(), ownerMmd.getName(), "" + c.size())); } delegate.clear(); delegate.addAll(c); } } }