All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.descriptors.SelectedFieldsLockingPolicy Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2024 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.descriptors;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.queries.ObjectLevelModifyQuery;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 

* Purpose: An implementation of the OptimisticLockingPolicy interface. * This policy compares selected fields in the WHERE clause when doing an update * or a delete. If any field has been changed, an optimistic locking exception * will be thrown. Note that the fields specified must be mapped and not be * primary keys. *

* NOTE: This policy can only be used inside a unit of work. * * @since TopLink 2.5 */ public class SelectedFieldsLockingPolicy extends FieldsLockingPolicy { protected Map> lockFieldsByTable; protected List lockFields; /** * PUBLIC: Create a new selected fields locking policy. A field locking * policy is based on locking on the specified fields by comparing with * their previous values to detect field-level collisions. Note: the unit of * work must be used for all updates when using field locking. */ public SelectedFieldsLockingPolicy() { super(); this.lockFieldsByTable = new HashMap<>(4); this.lockFields = new ArrayList<>(); } /** * PUBLIC: Add a field name to lock on. All fields in this list will be * compared when updating if the value of any of the fields does not match * the value in memory, an OptimisticLockException will be thrown. *

* Note: An Automatic update will not be done on this field, only a * comparison occurs. */ public void addLockFieldName(String fieldName) { getLockFields().add(new DatabaseField(fieldName)); } /** * INTERNAL: Values to be included in the locking mechanism are added to the * translation row. For changed fields the normal build row is ok as only * changed fields matter. */ @Override public void addLockValuesToTranslationRow(ObjectLevelModifyQuery query) throws DatabaseException { Object object; verifyUsage(query.getSession()); if (query.isDeleteObjectQuery()) { object = query.getObject(); } else { object = query.getBackupClone(); } // EL bug 319759 if (query.isUpdateObjectQuery()) { query.setShouldValidateUpdateCallCacheUse(true); } for (Iterator> fields = getLockFieldsByTable().values().iterator(); fields.hasNext();) { for (DatabaseField field : fields.next()) { DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForField(field); // Bug5892889, Exception will be thrown if no matched database // field found if (mapping == null) { throw DatabaseException.specifiedLockingFieldsNotFoundInDatabase(field.getQualifiedName()); } else { mapping.writeFromObjectIntoRow(object, query.getTranslationRow(), query.getSession(), WriteType.UNDEFINED); } } } } /** * INTERNAL: returns the lock fields to compare based on the passed in * table. */ @Override protected List getFieldsToCompare(org.eclipse.persistence.internal.helper.DatabaseTable table, AbstractRecord transRow, AbstractRecord modifyRow) { return getLockFields(table); } /** * INTERNAL: Returns the lock fields */ public List getLockFields() { return lockFields; } /** * INTERNAL: returns the lock fields based on the passed in table */ protected List getLockFields(DatabaseTable table) { List temp = this.lockFieldsByTable.get(table); if (temp == null) { return Collections.emptyList(); } return temp; } /** * INTERNAL: returns the lock fields */ protected Map> getLockFieldsByTable() { return lockFieldsByTable; } /** * INTERNAL: It is responsible for initializing the policy; */ @Override public void initialize(AbstractSession session) { super.initialize(session); List lockFields = getLockFields(); int size = lockFields.size(); for (int index = 0; index < size; index++) { DatabaseField field = lockFields.get(index); field = descriptor.buildField(field); lockFields.set(index, field); List fieldsForTable = getLockFieldsByTable().computeIfAbsent(field.getTable(), k -> new ArrayList<>()); fieldsForTable.add(field); } } /** * PUBLIC: Set the field names to lock on. All fields in this list will be * compared when Updating. If the value of any of the fields does not match * the value in memory, an OptimisticLockException will be thrown. *

* Note: An Automatic update will not be done on this field, only a * comparison occurs. */ public void setLockFieldNames(List lockFieldNames) { for (String name : lockFieldNames) { addLockFieldName(name); } } /** * INTERNAL: Sets the lock fields */ protected void setLockFields(List lockFields) { this.lockFields = lockFields; } /** * INTERNAL: Used to set the field names to be used in this policy. */ protected void setLockFieldsByTable(Map> lockFieldsByTable) { this.lockFieldsByTable = lockFieldsByTable; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy