use of org.datanucleus.metadata.ForeignKeyMetaData in project datanucleus-rdbms by datanucleus.
the class SecondaryTable method getExpectedForeignKeys.
/**
* Accessor for the expected foreign keys for this table.
* @return The expected foreign keys.
*/
protected List<ForeignKey> getExpectedForeignKeys() {
assertIsInitialized();
// Auto mode allows us to decide which FKs are needed as well as using what is in the users MetaData.
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
autoMode = true;
}
// Add FK back to the primary table unless requested not to
List<ForeignKey> foreignKeys = new ArrayList<>();
ForeignKeyMetaData fkmd = joinMetaData != null ? joinMetaData.getForeignKeyMetaData() : null;
if (autoMode || (fkmd != null && fkmd.getDeleteAction() != ForeignKeyAction.NONE)) {
ForeignKey fk = new ForeignKey(getIdMapping(), dba, primaryTable, fkmd != null && fkmd.isDeferred() ? true : false);
if (fkmd != null && fkmd.getName() != null) {
fk.setName(fkmd.getName());
}
foreignKeys.add(0, fk);
}
return foreignKeys;
}
use of org.datanucleus.metadata.ForeignKeyMetaData in project datanucleus-rdbms by datanucleus.
the class TableUtils method getForeignKeyForPCField.
/**
* Convenience method to add a foreign key for a PC field.
* Adds a FK from the PC column(s) in this table to the ID columns in the PC's table.
* @param fieldMapping Mapping for the PC field
* @param mmd MetaData for the field
* @param autoMode Whether we are in auto-create mode
* @param storeMgr Store Manager
* @param clr ClassLoader resolver
* @return The ForeignKey (if any)
*/
public static ForeignKey getForeignKeyForPCField(JavaTypeMapping fieldMapping, AbstractMemberMetaData mmd, boolean autoMode, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
DatastoreClass referencedTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (referencedTable == null) {
// PC type uses subclass-table
AbstractClassMetaData refCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
if (refCmd != null) {
AbstractClassMetaData[] refCmds = storeMgr.getClassesManagingTableForClass(refCmd, clr);
if (refCmds != null && refCmds.length == 1) {
referencedTable = storeMgr.getDatastoreClass(refCmds[0].getFullClassName(), clr);
} else {
// "subclass-table" with more than 1 subclass with table (not supported)
}
}
}
if (referencedTable != null) {
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if ((fkmd != null && (fkmd.getDeleteAction() != ForeignKeyAction.NONE || fkmd.getFkDefinitionApplies())) || autoMode) {
// Either has been specified by user, or using autoMode, so add FK
ForeignKey fk = new ForeignKey(fieldMapping, storeMgr.getDatastoreAdapter(), referencedTable, true);
// Does nothing when no FK MetaData
fk.setForMetaData(fkmd);
if (fkmd != null && fkmd.getName() != null) {
fk.setName(fkmd.getName());
}
return fk;
}
}
return null;
}
use of org.datanucleus.metadata.ForeignKeyMetaData in project datanucleus-rdbms by datanucleus.
the class DeleteRequest method updateOneToOneBidirectionalOwnerObjectForField.
/**
* Method to update any 1-1 bidir non-owner fields where the foreign-key is stored in the other object.
* @param op ObjectProvider of this object
* @param mmd MetaData for field that has related (owner) objects
*/
private void updateOneToOneBidirectionalOwnerObjectForField(ObjectProvider op, AbstractMemberMetaData fmd) {
if (softDeleteStmt != null) {
// If we are soft deleting the owner then no need to null the linkage BUT we need to check the soft delete status on retrieval of the owner from related
return;
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052217", op.getObjectAsPrintable(), fmd.getFullFieldName()));
}
RDBMSStoreManager storeMgr = table.getStoreManager();
ExecutionContext ec = op.getExecutionContext();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
AbstractMemberMetaData[] relatedMmds = fmd.getRelatedMemberMetaData(clr);
// Check if we should null here, or leave to the datastore FK handler
boolean checkFK = true;
if (ec.getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
// JDO2 doesn't currently (2.0 spec) take note of foreign-key
checkFK = false;
}
if (checkFK) {
for (int i = 0; i < relatedMmds.length; i++) {
ForeignKeyMetaData relFkmd = relatedMmds[i].getForeignKeyMetaData();
if (relFkmd != null && relFkmd.getDeleteAction() != null) {
// Field has a FK with a delete-action so leave to the datastore to process the delete
return;
}
}
}
// TODO Cater for more than 1 related field
String fullClassName = ((AbstractClassMetaData) relatedMmds[0].getParent()).getFullClassName();
// TODO I'm not sure that we need to loop all implementations. will we have the fk set to all tables, if many?
String[] classes;
if (((AbstractClassMetaData) relatedMmds[0].getParent()) instanceof InterfaceMetaData) {
classes = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(fullClassName, clr);
} else {
classes = new String[] { fullClassName };
}
Set<DatastoreClass> datastoreClasses = new HashSet();
for (int i = 0; i < classes.length; i++) {
// just remove duplicates
datastoreClasses.add(storeMgr.getDatastoreClass(classes[i], clr));
}
Iterator<DatastoreClass> it = datastoreClasses.iterator();
while (it.hasNext()) {
DatastoreClass refTable = it.next();
JavaTypeMapping refMapping = refTable.getMemberMapping(fmd.getMappedBy());
if (// Only clear the references that can be cleared
refMapping.isNullable()) {
// Create a statement to clear the link from the previous related object
StringBuilder clearLinkStmt = new StringBuilder("UPDATE " + refTable.toString() + " SET ");
for (int j = 0; j < refMapping.getNumberOfDatastoreMappings(); j++) {
if (j > 0) {
clearLinkStmt.append(",");
}
clearLinkStmt.append(refMapping.getDatastoreMapping(j).getColumn().getIdentifier());
clearLinkStmt.append("=NULL");
}
clearLinkStmt.append(" WHERE ");
for (int j = 0; j < refMapping.getNumberOfDatastoreMappings(); j++) {
if (j > 0) {
clearLinkStmt.append(" AND ");
}
clearLinkStmt.append(refMapping.getDatastoreMapping(j).getColumn().getIdentifier());
clearLinkStmt.append("=?");
}
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
// Null out the relationship to the object being deleted.
PreparedStatement ps = null;
try {
ps = sqlControl.getStatementForUpdate(mconn, clearLinkStmt.toString(), false);
refMapping.setObject(ec, ps, MappingHelper.getMappingIndices(1, refMapping), op.getObject());
sqlControl.executeStatementUpdate(ec, mconn, clearLinkStmt.toString(), ps, true);
} finally {
if (ps != null) {
sqlControl.closeStatement(mconn, ps);
}
}
} finally {
mconn.release();
}
} catch (Exception e) {
throw new NucleusDataStoreException("Update request failed", e);
}
}
}
}
use of org.datanucleus.metadata.ForeignKeyMetaData in project datanucleus-api-jdo by datanucleus.
the class KeyMetadataImpl method getForeignKeyMetadata.
/* (non-Javadoc)
* @see javax.jdo.metadata.KeyMetadata#getForeignKeyMetadata()
*/
public ForeignKeyMetadata getForeignKeyMetadata() {
ForeignKeyMetaData internalFkmd = getInternal().getForeignKeyMetaData();
if (internalFkmd == null) {
return null;
}
ForeignKeyMetadataImpl fkmd = new ForeignKeyMetadataImpl(internalFkmd);
fkmd.parent = this;
return fkmd;
}
use of org.datanucleus.metadata.ForeignKeyMetaData in project datanucleus-api-jdo by datanucleus.
the class MemberMetadataImpl method getForeignKeyMetadata.
public ForeignKeyMetadata getForeignKeyMetadata() {
ForeignKeyMetaData internalFkmd = getInternal().getForeignKeyMetaData();
if (internalFkmd == null) {
return null;
}
ForeignKeyMetadataImpl fkmd = new ForeignKeyMetadataImpl(internalFkmd);
fkmd.parent = this;
return fkmd;
}
Aggregations