/** * INTERNAL: * The selection queries are created by cloning the source mapping, * updating the necessary database fields on the mapping and then * initializing the mapping to create the internal selection query. * This query is then cached where needed using the source mapping * as the key. A prepare is performed for each child of the hierarchy. */ protected void prepareSelectionQuery(DatabaseMapping sourceMapping, AbstractSession session) { // Recurse through our child descriptors to set up the selection query // before execution. for (ClassDescriptor childDescriptor : (Vector<ClassDescriptor>) getChildDescriptors()) { childDescriptor.getTablePerClassPolicy().prepareSelectionQuery(sourceMapping, session); } if (sourceMapping.isOneToManyMapping()) { prepareOneToManySelectionQuery((OneToManyMapping) sourceMapping, session); } else if (sourceMapping.isManyToManyMapping()) { prepareManyToManySelectionQuery((ManyToManyMapping) sourceMapping, session); } else if (sourceMapping.isOneToOneMapping()) { prepareOneToOneSelectionQuery((OneToOneMapping) sourceMapping, session); } // No support for other mappings at this point. }
/** * INTERNAL: * Create a new policy. * Only descriptors involved in inheritance should have a policy. */ public TablePerClassPolicy(ClassDescriptor descriptor) { setDescriptor(descriptor); }
/** * INTERNAL: * This method is called from individual mappings during their * initialization. If the mapping is to a class within a TABLE_PER_CLASS * inheritance hierarchy, what this method will do is prepare a selection * query to execute for every child descriptor in the hierarchy. * * The selection queries are created by cloning the source mapping, * updating the necessary database fields on the mapping and then * initializing the mapping to create the internal selection query. * This query is then cached where needed using the source mapping's * selection query name as the key. * * @see selectAllObjects(ReadAllQuery) * @see selectOneObject(ReadObjectQuery) */ public void prepareChildrenSelectionQuery(DatabaseMapping sourceMapping, AbstractSession session) { // From collection mappings we must execute a query on every // subclass table to build our results. Tell all children // descriptors to prepare their selection queries. for (ClassDescriptor childDescriptor : (Vector<ClassDescriptor>) getChildDescriptors()) { childDescriptor.getTablePerClassPolicy().prepareSelectionQuery(sourceMapping, session); } }
result = containerPolicy.concatenateContainers(result, getDescriptor().getTablePerClassPolicy().selectAllObjectsUsingMultipleTableSubclassRead(this));
&& (this.descriptor.getTablePerClassPolicy().getChildDescriptors().size() > 0)) { getConcreteSubclassQueries();
/** * Build field definitions and foreign key constraints for all many-to-many relation table. */ protected void buildRelationTableFields(ForeignReferenceMapping mapping, TableDefinition table, List<DatabaseField> fkFields, List<DatabaseField> targetFields) { assert fkFields.size() > 0 && fkFields.size() == targetFields.size(); DatabaseField fkField = null; DatabaseField targetField = null; List<String> fkFieldNames = new ArrayList(); List<String> targetFieldNames = new ArrayList(); for (int index = 0; index < fkFields.size(); index++) { fkField = fkFields.get(index); targetField = targetFields.get(index); fkFieldNames.add(fkField.getNameDelimited(databasePlatform)); targetFieldNames.add(targetField.getNameDelimited(databasePlatform)); fkField = resolveDatabaseField(fkField, targetField); setFieldToRelationTable(fkField, table); } // add a foreign key constraint from fk field to target field DatabaseTable targetTable = targetField.getTable(); TableDefinition targetTblDef = getTableDefFromDBTable(targetTable); if (mapping.getDescriptor().hasTablePerClassPolicy()) { return; } if (mapping.getReferenceDescriptor().hasTablePerClassPolicy() && mapping.getReferenceDescriptor().getTablePerClassPolicy().hasChild()) { return; } addForeignKeyConstraint(table, targetTblDef, fkFieldNames, targetFieldNames, mapping.isCascadeOnDeleteSetOnDatabase()); }
descriptor.getClassDescriptor().getTablePerClassPolicy().addParentDescriptor(parentDescriptor.getClassDescriptor()); parentDescriptor.getClassDescriptor().getTablePerClassPolicy().addChildDescriptor(descriptor.getClassDescriptor()); } else {
/** * INTERNAL: */ protected void prepareOneToOneSelectionQuery(OneToOneMapping sourceMapping, AbstractSession session) { // Clone the mapping because in reality that is what we have, that // is, a 1-1 mapping to each class of the hierarchy. OneToOneMapping oneToOne = (OneToOneMapping) sourceMapping.clone(); // Update the target keys to have an empty table (descriptor will figure it out) for (DatabaseField targetField : oneToOne.getTargetToSourceKeyFields().keySet()) { targetField.setTable(new DatabaseTable()); } addSelectionQuery(oneToOne, sourceMapping, session); }
/** * INTERNAL: */ protected void addSelectionQuery(ForeignReferenceMapping cloneMapping, ForeignReferenceMapping sourceMapping, AbstractSession session) { // Set the new reference class cloneMapping.setReferenceClass(getDescriptor().getJavaClass()); cloneMapping.setReferenceClassName(getDescriptor().getJavaClassName()); // Force the selection criteria to be re-built. cloneMapping.setForceInitializationOfSelectionCriteria(true); // Now initialize the mapping cloneMapping.initialize(session); // The selection query should be initialized with all the right // goodies now, cache it for quick retrieval. ObjectLevelReadQuery selectionQuery = (ObjectLevelReadQuery) cloneMapping.getSelectionQuery(); selectionQuery.getExpressionBuilder().setQueryClassAndDescriptor(descriptor.getJavaClass(), descriptor); // By default its source mapping will be the cloned mapping, we // need to set the actual source mapping so that we can look it // back up correctly. selectionQuery.setSourceMapping(sourceMapping); // Cache the selection query for this source mapping. selectionQueriesForAllObjects.put(sourceMapping, selectionQuery); }
/** * INTERNAL: */ protected void setTablePerClassInheritancePolicy(MetadataDescriptor descriptor) { descriptor.getClassDescriptor().setTablePerClassPolicy(new TablePerClassPolicy(descriptor.getClassDescriptor())); }
result, this.descriptor.getTablePerClassPolicy().selectAllObjectsUsingMultipleTableSubclassRead(this), this.session);
&& (this.descriptor.getTablePerClassPolicy().getChildDescriptors().size() > 0)) { getConcreteSubclassQueries();
&& mapping.getReferenceDescriptor().getTablePerClassPolicy().hasChild()) { return;
/** * INTERNAL: */ protected void prepareOneToManySelectionQuery(OneToManyMapping sourceMapping, AbstractSession session) { // Clone the mapping because in reality that is what we have, that // is, a 1-M mapping to each class of the hierarchy. OneToManyMapping oneToMany = (OneToManyMapping) sourceMapping.clone(); // Update the foreign key fields on the mapping. Basically, take the // table name off and let the descriptor figure it out. Vector<DatabaseField> targetForeignKeyFields = new Vector<DatabaseField>(); for (DatabaseField fkField : oneToMany.getTargetForeignKeysToSourceKeys().keySet()) { targetForeignKeyFields.add(new DatabaseField(fkField.getName())); } // Update our foreign key fields and clear the key maps. oneToMany.setTargetForeignKeyFields(targetForeignKeyFields); oneToMany.getTargetForeignKeysToSourceKeys().clear(); oneToMany.getSourceKeysToTargetForeignKeys().clear(); addSelectionQuery(oneToMany, sourceMapping, session); }
/** * INTERNAL: * Select one object of any concrete subclass. */ @Override protected Object selectOneObject(ReadObjectQuery query) throws DescriptorException { // If we came from a source mapping the execute the selection query // we prepared from it. if (selectionQueriesForAllObjects.containsKey(query.getSourceMapping())) { return query.getExecutionSession().executeQuery(selectionQueriesForAllObjects.get(query.getSourceMapping()), query.getTranslationRow()); } else { // Assuming we're doing a find by primary key ... // We have to update the translation row to be to the correct field. AbstractRecord translationRow = (AbstractRecord) query.getTranslationRow().clone(); Vector allFields = new Vector(); for (DatabaseField field : (Vector<DatabaseField>) translationRow.getFields()) { // Remove the table and let the descriptor figure it out. allFields.add(new DatabaseField(field.getName())); } translationRow.getFields().clear(); translationRow.getFields().addAll(allFields); return query.getSession().executeQuery(getDescriptor().getQueryManager().getReadObjectQuery(), translationRow); } } }
/** * INTERNAL: * Create a new policy. * Only descriptors involved in inheritance should have a policy. */ public TablePerClassPolicy(ClassDescriptor descriptor) { setDescriptor(descriptor); }
result, this.descriptor.getTablePerClassPolicy().selectAllObjectsUsingMultipleTableSubclassRead(this), this.session);
protected void addForeignKeyFieldToSourceTargetTable(OneToOneMapping mapping) { if (!mapping.isForeignKeyRelationship() || (mapping.getReferenceDescriptor().hasTablePerClassPolicy() && mapping.getReferenceDescriptor().getTablePerClassPolicy().hasChild())) { return;
/** * INTERNAL: */ protected void prepareManyToManySelectionQuery(ManyToManyMapping sourceMapping, AbstractSession session) { // Clone the mapping because in reality that is what we have, that // is, a M-M mapping to each class of the hierarchy. ManyToManyMapping manyToMany = (ManyToManyMapping) sourceMapping.clone(); // Update the foreign key fields on the mapping. Basically, take the // table name off and let the descriptor figure it out. for (DatabaseField keyField : manyToMany.getTargetKeyFields()) { keyField.setTable(new DatabaseTable()); } addSelectionQuery(manyToMany, sourceMapping, session); }
/** * INTERNAL: * Create a new policy. * Only descriptors involved in inheritance should have a policy. */ public TablePerClassPolicy(ClassDescriptor descriptor) { setDescriptor(descriptor); selectionQueriesForAllObjects = new HashMap<DatabaseMapping, DatabaseQuery>(); }