mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-26 05:14:57 +00:00
HHH-8576 - Query not properly locking non-versioned entities associated with PersistenceContext
This commit is contained in:
parent
7c6b358d4f
commit
ffa67243b8
@ -1539,7 +1539,7 @@ private void instanceAlreadyLoaded(
|
||||
final Loadable persister,
|
||||
final EntityKey key,
|
||||
final Object object,
|
||||
final LockMode lockMode,
|
||||
final LockMode requestedLockMode,
|
||||
final SessionImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
if ( !persister.isInstance( object ) ) {
|
||||
@ -1547,23 +1547,18 @@ private void instanceAlreadyLoaded(
|
||||
"loaded object was of wrong class " + object.getClass(),
|
||||
key.getIdentifier(),
|
||||
persister.getEntityName()
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if ( LockMode.NONE != lockMode && upgradeLocks() ) { //no point doing this if NONE was requested
|
||||
|
||||
final boolean isVersionCheckNeeded = persister.isVersioned() &&
|
||||
session.getPersistenceContext().getEntry(object)
|
||||
.getLockMode().lessThan( lockMode );
|
||||
// we don't need to worry about existing version being uninitialized
|
||||
// because this block isn't called by a re-entrant load (re-entrant
|
||||
// loads _always_ have lock mode NONE)
|
||||
if (isVersionCheckNeeded) {
|
||||
if ( LockMode.NONE != requestedLockMode && upgradeLocks() ) { //no point doing this if NONE was requested
|
||||
final EntityEntry entry = session.getPersistenceContext().getEntry( object );
|
||||
if ( entry.getLockMode().lessThan( requestedLockMode ) ) {
|
||||
//we only check the version when _upgrading_ lock modes
|
||||
checkVersion( i, persister, key.getIdentifier(), object, rs, session );
|
||||
if ( persister.isVersioned() ) {
|
||||
checkVersion( i, persister, key.getIdentifier(), object, rs, session );
|
||||
}
|
||||
//we need to upgrade the lock mode to the mode requested
|
||||
session.getPersistenceContext().getEntry(object)
|
||||
.setLockMode(lockMode);
|
||||
entry.setLockMode( requestedLockMode );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,14 @@
|
||||
*/
|
||||
package org.hibernate.jpa.test.lock;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@ -49,7 +54,7 @@
|
||||
public class QueryLockingTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Lockable.class };
|
||||
return new Class[] { Lockable.class, LocalEntity.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -279,4 +284,73 @@ public void testOptimisticSpecific() {
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* lock some entities via a query and check the resulting lock mode type via EntityManager
|
||||
*/
|
||||
@Test
|
||||
public void testEntityLockModeStateAfterQueryLocking() {
|
||||
// Create some test data
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.persist( new LocalEntity( 1, "test" ) );
|
||||
em.getTransaction().commit();
|
||||
// em.close();
|
||||
|
||||
// issue the query with locking
|
||||
// em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
Query query = em.createQuery( "select l from LocalEntity l" );
|
||||
assertEquals( LockModeType.NONE, query.getLockMode() );
|
||||
query.setLockMode( LockModeType.PESSIMISTIC_READ );
|
||||
assertEquals( LockModeType.PESSIMISTIC_READ, query.getLockMode() );
|
||||
List<LocalEntity> results = query.getResultList();
|
||||
|
||||
// and check the lock mode for each result
|
||||
for ( LocalEntity e : results ) {
|
||||
assertEquals( LockModeType.PESSIMISTIC_READ, em.getLockMode( e ) );
|
||||
}
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
// clean up test data
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.createQuery( "delete from LocalEntity" ).executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Entity( name = "LocalEntity" )
|
||||
@Table( name = "LocalEntity" )
|
||||
public static class LocalEntity {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public LocalEntity() {
|
||||
}
|
||||
|
||||
public LocalEntity(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user