WrongClassException tests
This commit is contained in:
parent
e38f63a0cb
commit
6ec996f1d5
|
@ -11,11 +11,11 @@ import jakarta.persistence.Entity;
|
|||
|
||||
@Entity
|
||||
public class ExtendedEntity extends MyEntity {
|
||||
public ExtendedEntity() {
|
||||
protected ExtendedEntity() {
|
||||
}
|
||||
|
||||
public ExtendedEntity(final String uid, final String extendedValue) {
|
||||
super( uid );
|
||||
public ExtendedEntity(Integer id, String uid, String extendedValue) {
|
||||
super( id, uid );
|
||||
this.extendedValue = extendedValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.mapping.naturalid.inheritance.cache;
|
||||
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.NotImplementedYet;
|
||||
|
@ -19,22 +20,122 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ServiceRegistry( settings = @Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true" ) )
|
||||
@DomainModel( annotatedClasses = { MyEntity.class, ExtendedEntity.class } )
|
||||
@SessionFactory
|
||||
public class InheritedNaturalIdCacheTest {
|
||||
|
||||
@Test
|
||||
public void testProperLoadingByNaturalId(SessionFactoryScope scope) {
|
||||
// load the entities properly by natural-id
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final MyEntity base = session.bySimpleNaturalId( MyEntity.class ).load( "base" );
|
||||
assertThat( base ).isNotNull();
|
||||
|
||||
final ExtendedEntity extended = session.bySimpleNaturalId( ExtendedEntity.class ).load( "extended" );
|
||||
assertThat( extended ).isNotNull();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadWrongClassById(SessionFactoryScope scope) {
|
||||
clearCaches( scope );
|
||||
|
||||
// try to load `MyEntity#1` as an ExtendedEntity
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.byId( ExtendedEntity.class ).load( 1 );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotImplementedYet(
|
||||
strict = false,
|
||||
reason = "Because `MyEntity#1` is stored in the second level cache, the attempt to " +
|
||||
"access it throws `WrongClassException`. Not consistent with what happens " +
|
||||
"when the entity is not in the cache - `#testLoadWrongClassById`"
|
||||
)
|
||||
public void testLoadWrongClassByIdFromCache(SessionFactoryScope scope) {
|
||||
clearCaches( scope );
|
||||
|
||||
// load `MyEntity#1` into the cache
|
||||
scope.inTransaction( (session) -> {
|
||||
final MyEntity loaded = session.byId( MyEntity.class ).load( 1 );
|
||||
assertThat( loaded ).isNotNull();
|
||||
} );
|
||||
|
||||
final CacheImplementor cache = scope.getSessionFactory().getCache();
|
||||
assertThat( cache.containsEntity( MyEntity.class, 1 ) ).isTrue();
|
||||
|
||||
// now try to access it as an ExtendedEntity
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.byId( ExtendedEntity.class ).load( 1 );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadWrongClassByNaturalId(SessionFactoryScope scope) {
|
||||
clearCaches( scope );
|
||||
|
||||
// try to load `MyEntity#1` as an ExtendedEntity
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.bySimpleNaturalId( ExtendedEntity.class ).load( "base" );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotImplementedYet(
|
||||
strict = false,
|
||||
reason = "Because `MyEntity#1` is stored in the second level cache, the attempt to " +
|
||||
"access it throws `WrongClassException`. Not consistent with what happens " +
|
||||
"when the entity is not in the cache - `#testLoadWrongClassByNaturalId`"
|
||||
)
|
||||
public void testLoadWrongClassByNaturalIdFromCache(SessionFactoryScope scope) {
|
||||
clearCaches( scope );
|
||||
|
||||
// load `MyEntity#1` into the cache
|
||||
scope.inTransaction( (session) -> {
|
||||
final MyEntity loaded = session.bySimpleNaturalId( MyEntity.class ).load( "base" );
|
||||
assertThat( loaded ).isNotNull();
|
||||
} );
|
||||
|
||||
final CacheImplementor cache = scope.getSessionFactory().getCache();
|
||||
assertThat( cache.containsEntity( MyEntity.class, 1 ) ).isTrue();
|
||||
|
||||
// now try to access it as an ExtendedEntity
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.bySimpleNaturalId( ExtendedEntity.class ).load( "base" );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
private void clearCaches(SessionFactoryScope scope) {
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
final CacheImplementor cache = sessionFactory.getCache();
|
||||
|
||||
cache.evictEntityData( MyEntity.class );
|
||||
cache.evictEntityData( ExtendedEntity.class );
|
||||
|
||||
cache.evictNaturalIdData( MyEntity.class );
|
||||
cache.evictNaturalIdData( ExtendedEntity.class );
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void createTestData(SessionFactoryScope scope) {
|
||||
// create the data:
|
||||
// MyEntity#1
|
||||
// ExtendedEntity#1
|
||||
// ExtendedEntity#2
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
session.save( new MyEntity( "base" ) );
|
||||
session.save( new ExtendedEntity( "extended", "ext" ) );
|
||||
session.save( new MyEntity( 1, "base" ) );
|
||||
session.save( new ExtendedEntity( 2, "extended", "ext" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -45,66 +146,4 @@ public class InheritedNaturalIdCacheTest {
|
|||
(session) -> session.createQuery( "delete MyEntity" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotImplementedYet(
|
||||
reason = "We do not throw `WrongClassException` atm, we just return null",
|
||||
strict = false
|
||||
)
|
||||
public void testLoadingInheritedEntitiesByNaturalId(SessionFactoryScope scope) {
|
||||
// load the entities "properly" by natural-id
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final MyEntity entity = session.bySimpleNaturalId( MyEntity.class ).load( "base" );
|
||||
assertNotNull( entity );
|
||||
|
||||
final ExtendedEntity extendedEntity = session.bySimpleNaturalId( ExtendedEntity.class ).load( "extended" );
|
||||
assertNotNull( extendedEntity );
|
||||
}
|
||||
);
|
||||
|
||||
// baseline: loading the wrong class by id...
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
try {
|
||||
session.byId( ExtendedEntity.class ).load( 1L );
|
||||
fail( "Expecting WrongClassException" );
|
||||
}
|
||||
catch (WrongClassException expected) {
|
||||
// expected outcome
|
||||
}
|
||||
catch (Exception other) {
|
||||
throw new AssertionError(
|
||||
"Unexpected exception type : " + other.getClass().getName(),
|
||||
other
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// finally, attempt to load MyEntity#1 as an ExtendedEntity, which should
|
||||
// throw a `WrongClassException` same as above with loading by id
|
||||
//
|
||||
// NOTE : this is what fails currently
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
try {
|
||||
session.bySimpleNaturalId( ExtendedEntity.class ).load( "base" );
|
||||
fail( "Expecting WrongClassException" );
|
||||
}
|
||||
catch (WrongClassException expected) {
|
||||
// expected outcome
|
||||
}
|
||||
catch (Exception other) {
|
||||
throw new AssertionError(
|
||||
"Unexpected exception type : " + other.getClass().getName(),
|
||||
other
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ServiceRegistry( settings = @Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false" ) )
|
||||
@DomainModel( annotatedClasses = { MyEntity.class, ExtendedEntity.class } )
|
||||
|
@ -30,8 +28,8 @@ public class InheritedNaturalIdNoCacheTest {
|
|||
public void createTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
session.persist( new MyEntity( "base" ) );
|
||||
session.persist( new ExtendedEntity( "extended", "ext" ) );
|
||||
session.persist( new MyEntity( 1, "base" ) );
|
||||
session.persist( new ExtendedEntity( 2, "extended", "ext" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -45,69 +43,69 @@ public class InheritedNaturalIdNoCacheTest {
|
|||
|
||||
@Test
|
||||
public void testLoadRoot(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.byNaturalId( MyEntity.class )
|
||||
.using( "uid", "base" )
|
||||
.load();
|
||||
assertThat( myEntity, notNullValue() );
|
||||
}
|
||||
);
|
||||
scope.inTransaction( (session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.byNaturalId( MyEntity.class )
|
||||
.using( "uid", "base" )
|
||||
.load();
|
||||
assertThat( myEntity ).isNotNull();
|
||||
} );
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.bySimpleNaturalId( MyEntity.class )
|
||||
.load( "base" );
|
||||
assertThat( myEntity, notNullValue() );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.bySimpleNaturalId( MyEntity.class )
|
||||
.load( "extended" );
|
||||
assertThat( myEntity, notNullValue() );
|
||||
}
|
||||
);
|
||||
scope.inTransaction( (session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.bySimpleNaturalId( MyEntity.class )
|
||||
.load( "base" );
|
||||
assertThat( myEntity ).isNotNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadSubclass(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final ExtendedEntity extendedEntity = session
|
||||
.byNaturalId( ExtendedEntity.class )
|
||||
.using( "uid", "extended" )
|
||||
.load();
|
||||
assertThat( extendedEntity, notNullValue() );
|
||||
}
|
||||
);
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final ExtendedEntity extendedEntity = session
|
||||
.bySimpleNaturalId( ExtendedEntity.class )
|
||||
.load( "extended" );
|
||||
assertThat( extendedEntity, notNullValue() );
|
||||
}
|
||||
);
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity extendedEntity = session
|
||||
.byNaturalId( ExtendedEntity.class )
|
||||
.using( "uid", "extended" )
|
||||
.load();
|
||||
assertThat( extendedEntity ).isNotNull();
|
||||
} );
|
||||
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity extendedEntity = session
|
||||
.bySimpleNaturalId( ExtendedEntity.class )
|
||||
.load( "extended" );
|
||||
assertThat( extendedEntity ).isNotNull();
|
||||
} );
|
||||
|
||||
scope.inTransaction( (session) -> {
|
||||
final MyEntity myEntity = session
|
||||
.bySimpleNaturalId( MyEntity.class )
|
||||
.load( "extended" );
|
||||
assertThat( myEntity ).isNotNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadWrongClass(SessionFactoryScope scope) {
|
||||
public void testLoadWrongClassById(SessionFactoryScope scope) {
|
||||
// try to access the root (base) entity as subclass (extended)
|
||||
// - the outcome is different here depending on whether:
|
||||
// 1) caching is enabled && the natural-id resolution is cached -> WrongClassException
|
||||
// 2) otherwise -> return null
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
final ExtendedEntity loaded = session.bySimpleNaturalId( ExtendedEntity.class ).load( "base" );
|
||||
assertThat( loaded, nullValue() );
|
||||
}
|
||||
);
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.byId( ExtendedEntity.class ).load( 1 );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadWrongClassByNaturalId(SessionFactoryScope scope) {
|
||||
// try to access the root (base) entity as subclass (extended)
|
||||
// - the outcome is different here depending on whether:
|
||||
// 1) caching is enabled && the natural-id resolution is cached -> WrongClassException
|
||||
// 2) otherwise -> return null
|
||||
scope.inTransaction( (session) -> {
|
||||
final ExtendedEntity loaded = session.bySimpleNaturalId( ExtendedEntity.class ).load( "base" );
|
||||
assertThat( loaded ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,39 +6,38 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.mapping.naturalid.inheritance.cache;
|
||||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.annotations.NaturalIdCache;
|
||||
|
||||
import jakarta.persistence.Cacheable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
|
||||
@Entity
|
||||
@Cacheable
|
||||
@NaturalIdCache
|
||||
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||
public class MyEntity {
|
||||
private Long id;
|
||||
private Integer id;
|
||||
private String uid;
|
||||
|
||||
public MyEntity() {
|
||||
protected MyEntity() {
|
||||
}
|
||||
|
||||
public MyEntity(String uid) {
|
||||
public MyEntity(Integer id, String uid) {
|
||||
this.id = id;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "increment")
|
||||
@GenericGenerator(name = "increment", strategy = "increment")
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue