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

org.hibernate.LockMode Maven / Gradle / Ivy

The newest version!
/*
 * SPDX-License-Identifier: LGPL-2.1-or-later
 * Copyright Red Hat Inc. and Hibernate Authors
 */
package org.hibernate;

import jakarta.persistence.FindOption;
import jakarta.persistence.RefreshOption;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;

import jakarta.persistence.LockModeType;

import java.util.Locale;

/**
 * Instances represent a lock mode for a row of a relational
 * database table. It is not intended that users spend much time
 * worrying about locking since Hibernate usually obtains exactly
 * the right lock level automatically. Some "advanced" users may
 * wish to explicitly specify lock levels.
 * 

* A partial order of lock modes is defined such that every * optimistic lock mode is considered a weaker sort of lock than * evey pessimistic lock mode. If a session already holds a * stronger lock level on a given entity when a weaker lock level * is requested, then the request for the weaker lock level has * no effect. *

* Note that, in particular, a request for the optimistic lock * level {@link #OPTIMISTIC_FORCE_INCREMENT} on an entity for * which any pessimistic lock is already held has no effect, * and does not force a version increment. *

* This enumeration of lock modes competes with the JPA-defined * {@link LockModeType}, but offers additional options, including * {@link #UPGRADE_NOWAIT} and {@link #UPGRADE_SKIPLOCKED}. * * @author Gavin King * * @see Session#lock(Object, LockMode) * @see LockModeType * @see LockOptions * @see org.hibernate.annotations.OptimisticLocking */ public enum LockMode implements FindOption, RefreshOption { /** * No lock required. If an object is requested with this lock * mode, a {@link #READ} lock will be obtained if it turns out * to be necessary to actually read the state from the database, * rather than pull it from a cache. *

* This is the "default" lock mode, the mode requested by calling * {@link Session#get(Class, Object)} without passing an explicit * mode. It permits the state of an object to be retrieved from * the cache without the cost of database access. * * @see LockModeType#NONE */ NONE, /** * A shared lock. Objects in this lock mode were read from the * database in the current transaction, rather than being pulled * from a cache. *

* Note that, despite the similar names this lock mode is not the * same as the JPA-defined mode {@link LockModeType#READ}. */ READ, /** * A shared optimistic lock. Assumes that the current transaction * will not experience contention for the state of an entity. The * version will be checked near the end of the transaction, to * verify that this was indeed the case. *

* Only legal for versioned entity types. *

* Note that this lock mode is the same as the JPA-defined modes * {@link LockModeType#READ} and {@link LockModeType#OPTIMISTIC}. * * @see LockModeType#OPTIMISTIC */ OPTIMISTIC, /** * A kind of exclusive optimistic lock. Assumes that the current * transaction will not experience contention for the state of an * entity. The version will be checked and incremented near the * end of the transaction, to verify that this was indeed the * case, and to signal to concurrent optimistic readers that their * optimistic locks have failed. *

* Only legal for versioned entity types. * * @see LockModeType#OPTIMISTIC_FORCE_INCREMENT */ OPTIMISTIC_FORCE_INCREMENT, /** * An exclusive write lock. Objects in this lock mode were updated * or inserted in the database in the current transaction. *

* This lock mode is for internal use only and is not a legal * argument to {@link Session#get(Class, Object, LockMode)}, * {@link Session#refresh(Object, LockMode)}, or * {@link Session#lock(Object, LockMode)}. These methods throw * an exception if {@code WRITE} is given as an argument. *

* Note that, despite the similar names, this lock mode is not * the same as the JPA-defined mode {@link LockModeType#WRITE}. */ @Internal WRITE, /** * A pessimistic upgrade lock, obtained using an Oracle-style * {@code select for update nowait}. The semantics of this * lock mode, if the lock is successfully obtained, are the same * as {@link #PESSIMISTIC_WRITE}. If the lock is not immediately * available, an exception occurs. */ UPGRADE_NOWAIT, /** * A pessimistic upgrade lock, obtained using an Oracle-style * {@code select for update skip locked}. The semantics of this * lock mode, if the lock is successfully obtained, are the same * as {@link #PESSIMISTIC_WRITE}. But if the lock is not * immediately available, no exception occurs, but the locked * row is not returned from the database. */ UPGRADE_SKIPLOCKED, /** * A pessimistic shared lock, which prevents concurrent * transactions from writing the locked object. Obtained via * a {@code select for share} statement in dialects where this * syntax is supported, and via {@code select for update} in * other dialects. *

* On databases which do not support {@code for share}, this * lock mode is equivalent to {@link #PESSIMISTIC_WRITE}. * * @see LockModeType#PESSIMISTIC_READ */ PESSIMISTIC_READ, /** * A pessimistic upgrade lock, which prevents concurrent * transactions from reading or writing the locked object. * Obtained via a {@code select for update} statement. * * @see LockModeType#PESSIMISTIC_WRITE */ PESSIMISTIC_WRITE, /** * A pessimistic write lock which immediately increments * the version of the locked object. Obtained by immediate * execution of an {@code update} statement. *

* Only legal for versioned entity types. * * @see LockModeType#PESSIMISTIC_FORCE_INCREMENT */ PESSIMISTIC_FORCE_INCREMENT; /** * @return an instance with the same semantics as the given JPA * {@link LockModeType}. */ public static LockMode fromJpaLockMode(LockModeType lockMode) { return LockModeTypeHelper.getLockMode( lockMode ); } /** * @return an instance of the JPA-defined {@link LockModeType} * with similar semantics to the given {@code LockMode}. */ public static LockModeType toJpaLockMode(LockMode lockMode) { return LockModeTypeHelper.getLockModeType( lockMode ); } /** * @return an instance of the JPA-defined {@link LockModeType} * with similar semantics to this {@code LockMode}. */ public LockModeType toJpaLockMode() { return LockModeTypeHelper.getLockModeType( this ); } /** * Check if this lock mode is more restrictive than the given lock mode. * * @param mode LockMode to check * * @return true if this lock mode is more restrictive than given lock mode */ public boolean greaterThan(LockMode mode) { return level() > mode.level(); } /** * Check if this lock mode is less restrictive than the given lock mode. * * @param mode LockMode to check * * @return true if this lock mode is less restrictive than given lock mode */ public boolean lessThan(LockMode mode) { return level() < mode.level(); } /** * Does this lock mode require a {@linkplain jakarta.persistence.Version version}? * * @return {@code true} if this lock mode only applies to versioned entities */ public boolean requiresVersion() { return this == OPTIMISTIC || this == OPTIMISTIC_FORCE_INCREMENT || this == PESSIMISTIC_FORCE_INCREMENT; } public String toExternalForm() { final String externalForm = toString().toLowerCase(Locale.ROOT); return this == UPGRADE_NOWAIT || this == UPGRADE_SKIPLOCKED ? externalForm.replace('_', '-') : externalForm; } /** * Determines a partial order on the lock modes, * based on how "exclusive" the lock is. *

* Note that {@link #PESSIMISTIC_READ} is, quite * arbitrarily, treated as more exclusive than * {@link #OPTIMISTIC_FORCE_INCREMENT}. Thus, if * the program holds any pessimistic lock on an * instance, and requests * {@code OPTIMISTIC_FORCE_INCREMENT}, then no * forced version increment will occur. */ private int level() { return switch (this) { case NONE -> 0; case READ -> 1; case OPTIMISTIC -> 2; case OPTIMISTIC_FORCE_INCREMENT -> 3; case PESSIMISTIC_READ -> 4; case UPGRADE_NOWAIT, UPGRADE_SKIPLOCKED, PESSIMISTIC_WRITE -> 5; case PESSIMISTIC_FORCE_INCREMENT, WRITE -> 6; }; } public static LockMode fromExternalForm(String externalForm) { if ( externalForm == null ) { return NONE; } for ( LockMode lockMode : values() ) { if ( lockMode.toExternalForm().equalsIgnoreCase( externalForm ) ) { return lockMode; } } if ( externalForm.equalsIgnoreCase( "upgrade" ) ) { return PESSIMISTIC_WRITE; } throw new IllegalArgumentException( "Unable to interpret LockMode reference from incoming external form: " + externalForm ); } /** * @return an instance of {@link LockOptions} with this lock mode, and * all other settings defaulted. */ public LockOptions toLockOptions() { return switch (this) { case NONE -> LockOptions.NONE; case READ -> LockOptions.READ; case OPTIMISTIC -> LockOptions.OPTIMISTIC; case OPTIMISTIC_FORCE_INCREMENT -> LockOptions.OPTIMISTIC_FORCE_INCREMENT; case UPGRADE_NOWAIT -> LockOptions.UPGRADE_NOWAIT; case UPGRADE_SKIPLOCKED -> LockOptions.UPGRADE_SKIPLOCKED; case PESSIMISTIC_READ -> LockOptions.PESSIMISTIC_READ; case PESSIMISTIC_WRITE -> LockOptions.PESSIMISTIC_WRITE; case PESSIMISTIC_FORCE_INCREMENT -> LockOptions.PESSIMISTIC_FORCE_INCREMENT; case WRITE -> throw new UnsupportedOperationException( "WRITE is not a valid LockMode as an argument" ); }; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy