| /* |
| * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // 11/10/2011-2.4 Guy Pelletier |
| // - 357474: Address primaryKey option from tenant discriminator column |
| package org.eclipse.persistence.mappings; |
| |
| import org.eclipse.persistence.exceptions.DescriptorException; |
| import org.eclipse.persistence.internal.descriptors.MultitenantPrimaryKeyAccessor; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| import org.eclipse.persistence.internal.identitymaps.CacheKey; |
| import org.eclipse.persistence.internal.queries.JoinedAttributeManager; |
| import org.eclipse.persistence.internal.sessions.AbstractRecord; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.internal.sessions.ChangeRecord; |
| import org.eclipse.persistence.internal.sessions.MergeManager; |
| import org.eclipse.persistence.internal.sessions.ObjectChangeSet; |
| import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl; |
| import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping; |
| import org.eclipse.persistence.queries.ObjectBuildingQuery; |
| import org.eclipse.persistence.sessions.Session; |
| |
| /** |
| * <b>Purpose</b>: Maps a multitenant property to the corresponding database |
| * field type. The list of field types that are supported by EclipseLink's |
| * direct to field mapping is dependent on the relational database being used. |
| * |
| * @author Guy Pelletier |
| * @since EclipseLink 2.4 |
| */ |
| public class MultitenantPrimaryKeyMapping extends AbstractColumnMapping { |
| private MultitenantPrimaryKeyAccessor accessor; |
| |
| /** |
| * Constructor |
| */ |
| public MultitenantPrimaryKeyMapping() { |
| super(); |
| |
| isInsertable = true; |
| isUpdatable = false; |
| setIsOptional(false); |
| accessor = new MultitenantPrimaryKeyAccessor(); |
| setAttributeAccessor(accessor); |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the attribute from the clone and assign it to the backup. |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public void buildBackupClone(Object clone, Object backup, UnitOfWorkImpl unitOfWork) { |
| // Mapping is write only so nothing to do. |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the attribute from the original and assign it to the clone. |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public void buildClone(Object original, CacheKey cacheKey, Object clone, Integer refreshCascade, AbstractSession cloningSession) { |
| // Mapping is write only so nothing to do. |
| } |
| |
| /** |
| * INTERNAL: |
| * Extract value from the row and set the attribute to this value in the |
| * working copy clone. |
| * In order to bypass the shared cache when in transaction a UnitOfWork must |
| * be able to populate working copies directly from the row. |
| */ |
| @Override |
| public void buildCloneFromRow(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) { |
| // Mapping is write only so nothing to do. |
| } |
| |
| /** |
| * INTERNAL: |
| * Compare the clone and backup clone values and return a change record if |
| * the value changed. |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) { |
| // Mapping is write only so nothing to do. |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Compare the attributes belonging to this mapping for the objects. |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) { |
| // Mapping is write only so nothing to do. |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public Object getFieldValue(Object propertyValue, AbstractSession session) { |
| return accessor.getValue(session); |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public Object getObjectValue(Object fieldValue, Session session) { |
| return accessor.getValue(session); |
| } |
| |
| /** |
| * INTERNAL: |
| * The mapping is initialized with the given session. This mapping is fully |
| * initialized after this. |
| */ |
| @Override |
| public void initialize(AbstractSession session) throws DescriptorException { |
| super.initialize(session); |
| |
| if (getField() == null) { |
| session.getIntegrityChecker().handleError(DescriptorException.fieldNameNotSetInMapping(this)); |
| } |
| |
| setField(getDescriptor().buildField(getField())); |
| setFields(collectFields()); |
| |
| // Must unwrap Struct types on WLS. |
| if (getField().getSqlType() == java.sql.Types.STRUCT) { |
| getDescriptor().setIsNativeConnectionRequired(true); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if this mapping requires its attribute value to be cloned. |
| */ |
| @Override |
| public boolean isCloningRequired() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| */ |
| @Override |
| public boolean isMultitenantPrimaryKeyMapping() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public boolean isRelationalMapping() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL |
| * This mapping must be write only as their is no attribute to read into. |
| */ |
| @Override |
| public boolean isWriteOnly() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| * Merge changes from the source to the target object. |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) { |
| // Mapping is write only so do nothing. |
| } |
| |
| /** |
| * INTERNAL: |
| * Merge changes from the source to the target object. This merge is only |
| * called when a changeSet for the target does not exist or the target is |
| * uninitialized |
| * |
| * This is an override from DatabaseMapping and must be implemented. |
| */ |
| @Override |
| public void mergeIntoObject(Object target, boolean isTargetUninitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) { |
| // Mapping is write only so do nothing. |
| } |
| |
| /** |
| * INTERNAL: |
| * The context property that is used to write this mapping must be set. It |
| * is set as the attribute name (which gets set on the accessor) |
| */ |
| public void setContextProperty(String contextProperty) { |
| setAttributeName(contextProperty); |
| } |
| |
| /** |
| * INTERNAL: |
| * Get a value from the object and set that in the respective field of the row. |
| */ |
| @Override |
| public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session, WriteType writeType) { |
| writeValueIntoRow(row, getField(), getFieldValue(null, session)); |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the Value from the object. |
| */ |
| @Override |
| public Object valueFromObject(Object anObject, DatabaseField field, AbstractSession session) { |
| return accessor.getValue(session); |
| } |
| |
| /** |
| * INTERNAL: |
| * Write fields needed for insert into the template for with null values. |
| */ |
| @Override |
| public void writeInsertFieldsIntoRow(AbstractRecord databaseRow, AbstractSession session) { |
| databaseRow.add(getField(), null); |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| protected void writeValueIntoRow(AbstractRecord row, DatabaseField field, Object fieldValue) { |
| row.add(getField(), fieldValue); |
| } |
| } |