org.datanucleus.store.rdbms.table.PersistableJoinTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-rdbms Show documentation
Show all versions of datanucleus-rdbms Show documentation
Plugin for DataNucleus providing persistence to RDBMS datastores.
/**********************************************************************
Copyright (c) 2010 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.table;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.ColumnMetaData;
import org.datanucleus.metadata.FieldRole;
import org.datanucleus.metadata.ForeignKeyMetaData;
import org.datanucleus.metadata.UniqueMetaData;
import org.datanucleus.store.rdbms.exceptions.NoTableManagedException;
import org.datanucleus.store.rdbms.RDBMSPropertyNames;
import org.datanucleus.store.rdbms.RDBMSStoreManager;
import org.datanucleus.store.rdbms.identifier.DatastoreIdentifier;
import org.datanucleus.store.rdbms.identifier.IdentifierFactory;
import org.datanucleus.store.rdbms.key.CandidateKey;
import org.datanucleus.store.rdbms.key.ForeignKey;
import org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
/**
* Representation of a join table for the case where we have an N-1 unidirectional relation
* stored in a join table. It's a minority interest situation, but worth inclusion.
* The "owner" in this case is the side with the relation (the "N" side). The "related" is the other side.
*/
public class PersistableJoinTable extends JoinTable
{
/** Table of the owner of this member. */
protected Table ownerTable;
/** Mapping from the join table to the "related". This will be a PersistableMapping. */
protected JavaTypeMapping relatedMapping;
/**
* Constructor.
* @param ownerTable Table of the owner of this member.
* @param tableName The Table SQL identifier
* @param mmd Member meta data for the "element" member.
* @param storeMgr Manager for the datastore.
*/
public PersistableJoinTable(Table ownerTable, DatastoreIdentifier tableName, AbstractMemberMetaData mmd, RDBMSStoreManager storeMgr)
{
super(ownerTable, tableName, mmd, storeMgr);
}
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.DatastoreContainerObject#getMemberMapping(org.datanucleus.metadata.AbstractMemberMetaData)
*/
public JavaTypeMapping getMemberMapping(AbstractMemberMetaData mmd)
{
return null;
}
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.table.Table#initialize(org.datanucleus.ClassLoaderResolver)
*/
public void initialize(ClassLoaderResolver clr)
{
boolean pkRequired = requiresPrimaryKey();
// Add owner mapping
ColumnMetaData[] ownerColmd = null;
if (mmd.getColumnMetaData() != null && mmd.getColumnMetaData().length > 0)
{
// Column mappings defined at this side via
ownerColmd = mmd.getColumnMetaData();
}
ownerMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(mmd.getClassName(true)), mmd,
ownerColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_OWNER, clr, null);
if (NucleusLogger.DATASTORE.isDebugEnabled())
{
logMapping(mmd.getFullFieldName()+".[OWNER]", ownerMapping);
}
// Add related mapping
ColumnMetaData[] relatedColmd = null;
if (mmd.getJoinMetaData().getColumnMetaData() != null &&
mmd.getJoinMetaData().getColumnMetaData().length > 0)
{
// Column mappings defined at this side via
relatedColmd = mmd.getJoinMetaData().getColumnMetaData();
}
relatedMapping = ColumnCreator.createColumnsForJoinTables(mmd.getType(), mmd,
relatedColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_PERSISTABLE_RELATION, clr, null);
if (NucleusLogger.DATASTORE.isDebugEnabled())
{
logMapping(mmd.getFullFieldName()+".[RELATED]", relatedMapping);
}
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
}
storeMgr.registerTableInitialized(this);
state = TABLE_STATE_INITIALIZED;
}
/**
* Accessor for the expected foreign keys for this table.
* @param clr The ClassLoaderResolver
* @return The expected foreign keys.
*/
public List getExpectedForeignKeys(ClassLoaderResolver clr)
{
assertIsInitialized();
// Find the mode that we're operating in for FK addition
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus"))
{
autoMode = true;
}
ArrayList foreignKeys = new ArrayList();
try
{
// FK from join table to owner table
DatastoreClass referencedTable = storeMgr.getDatastoreClass(mmd.getClassName(true), clr);
if (referencedTable != null)
{
// Single owner table, so add a single FK to the owner as appropriate
// Take from
ForeignKey fk = null;
ForeignKeyMetaData fkmd = null;
if (mmd.getJoinMetaData() != null)
{
fkmd = mmd.getJoinMetaData().getForeignKeyMetaData();
}
if (fkmd != null || autoMode)
{
fk = new ForeignKey(ownerMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
}
if (fk != null)
{
foreignKeys.add(fk);
}
}
// FK from join table to related table
referencedTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (referencedTable != null)
{
// Take from
ForeignKey fk = null;
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if (fkmd != null || autoMode)
{
fk = new ForeignKey(relatedMapping, dba, referencedTable, true);
fk.setForMetaData(fkmd);
}
if (fk != null)
{
foreignKeys.add(fk);
}
}
}
catch (NoTableManagedException e)
{
// expected when no table exists
}
return foreignKeys;
}
/**
* Accessor for the indices for this table.
* This includes both the user-defined indices (via MetaData), and the ones required by
* foreign keys (required by relationships).
* @param clr The ClassLoaderResolver
* @return The indices
*/
protected Set getExpectedIndices(ClassLoaderResolver clr)
{
// The indices required by foreign keys (BaseTable)
Set indices = super.getExpectedIndices(clr);
return indices;
}
/**
* Accessor for the candidate keys for this table.
* @return The indices
*/
protected List getExpectedCandidateKeys()
{
// The indices required by foreign keys (BaseTable)
List candidateKeys = super.getExpectedCandidateKeys();
if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getUniqueMetaData() != null)
{
// User has defined a unique key on the join table
UniqueMetaData unimd = mmd.getJoinMetaData().getUniqueMetaData();
if (unimd.getNumberOfColumns() > 0)
{
String[] columnNames = unimd.getColumnNames();
CandidateKey uniKey = new CandidateKey(this, null);
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
for (String columnName : columnNames)
{
Column col = getColumn(idFactory.newColumnIdentifier(columnName));
if (col != null)
{
uniKey.addColumn(col);
}
else
{
throw new NucleusUserException("Unique key on join-table " + this + " has column " +
columnName + " that is not found");
}
}
candidateKeys.add(uniKey);
}
}
return candidateKeys;
}
/**
* Accessor for the mapping of the "related" in the join table.
* @return The column mapping for the related side.
*/
public JavaTypeMapping getRelatedMapping()
{
assertIsInitialized();
return relatedMapping;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy