Hibernate: Scope of pessimistic locks within transaction

644 Views Asked by At

I am using Hibernate for ORM for a game server and just switched from session/transaction per unit of work to session/transaction per request.

Since multiple transactions may conflict with each other I am using pessimistic locking. The problem is that I frequently run into deadlocks. Now my question is whether it is possible to explicitly define the scope within a transaction in which a specific entity instance is locked or whether after specifying the lock mode the instance is locked until I commit the transaction?

If the latter holds true , how could I avoid deadlocks within a session-transaction per request environment If I can’t arbitrarily schedule method calls of methods that lock resources in the database?

1

There are 1 best solutions below

0
On

Locks are always bound to the transaction, that's how databases work. You should keep your transactions as small as possible, so I would recommend you to stick with a transaction per unit of work. Note that you can have multiple transactions for a session though.

I don't know why you switched to session per request, but I guess due to lazy loading issues? Believe me, this is not a solution and comes with many other issues. To solve lazy loading issues, one usually uses entity graphs and/or DTOs.

I think this is a perfect use case for Blaze-Persistence Entity Views.

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

A DTO model could look like the following with Blaze-Persistence Entity-Views:

@EntityView(User.class)
public interface UserDto {
    @IdMapping
    Long getId();
    String getName();
    Set<RoleDto> getRoles();

    @EntityView(Role.class)
    interface RoleDto {
        @IdMapping
        Long getId();
        String getName();
    }
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

UserDto a = entityViewManager.find(entityManager, UserDto.class, id);

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features