HHH-16108 Test a (simple) entity update for models with bytecode enhancement and multiple one-to-one associations (some lazy)
Stack trace: java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.SelectableMapping.isFormula()" because "selectable" is null at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.processSet(UpdateCoordinatorStandard.java:665) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.processAttribute(UpdateCoordinatorStandard.java:640) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.analyzeUpdateValues(UpdateCoordinatorStandard.java:600) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:256) at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.coordinateUpdate(UpdateCoordinatorStandard.java:203) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2766) at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:165) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:616) at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:487) at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:484) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485) at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2277) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1942) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:426) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) at org.hibernate.testing.transaction.TransactionUtil2.inTransaction(TransactionUtil2.java:128) at org.hibernate.testing.transaction.TransactionUtil2.lambda$inTransaction$0(TransactionUtil2.java:76) at org.hibernate.testing.transaction.TransactionUtil2.inSession(TransactionUtil2.java:35) at org.hibernate.testing.transaction.TransactionUtil2.inTransaction(TransactionUtil2.java:74) at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.inTransaction(BaseNonConfigCoreFunctionalTestCase.java:590) at org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.LazyOneToOneMultiLevelTest.testPersist(LazyOneToOneMultiLevelTest.java:56) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
This commit is contained in:
parent
6c385f7890
commit
6bc1b24443
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bytecode.enhancement.lazy.proxy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.OneToOne;
|
||||
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
@EnhancementOptions(lazyLoading = true)
|
||||
@TestForIssue(jiraKey = "HHH-16108")
|
||||
public class LazyOneToOneMultiAssociationTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
public Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { EntityA.class, EntityB.class };
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepare() {
|
||||
inTransaction( s -> {
|
||||
EntityA entityA = new EntityA( 1 );
|
||||
s.persist( entityA );
|
||||
} );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
inTransaction( s -> {
|
||||
s.createMutationQuery( "delete entityb" ).executeUpdate();
|
||||
s.createMutationQuery( "delete entitya" ).executeUpdate();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersist() {
|
||||
inTransaction( s -> {
|
||||
EntityA entityA = s.get( EntityA.class, 1 );
|
||||
EntityB entityB = new EntityB( 2 );
|
||||
entityA.setMappedAssociation1( entityB );
|
||||
entityB.setAssociation1( entityA );
|
||||
s.persist( entityB );
|
||||
// Without a fix, this ends up failing during the flush:
|
||||
// java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.SelectableMapping.isFormula()" because "selectable" is null
|
||||
// at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.processSet(UpdateCoordinatorStandard.java:665)
|
||||
} );
|
||||
|
||||
inTransaction( s -> {
|
||||
EntityA entityA = s.get( EntityA.class, 1 );
|
||||
assertThat( entityA ).isNotNull();
|
||||
|
||||
assertFalse( Hibernate.isPropertyInitialized( entityA, "mappedAssociation1" ) );
|
||||
EntityB entityB = entityA.getMappedAssociation1();
|
||||
|
||||
assertThat( entityB ).isNotNull();
|
||||
assertThat( entityB.getAssociation1() ).isEqualTo( entityA );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "entitya")
|
||||
public static class EntityA {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@OneToOne
|
||||
private EntityA selfAssociation;
|
||||
|
||||
@OneToOne(mappedBy = "selfAssociation")
|
||||
private EntityA mappedSelfAssociation;
|
||||
|
||||
@OneToOne(mappedBy = "association1", fetch = FetchType.LAZY)
|
||||
private EntityB mappedAssociation1;
|
||||
|
||||
@OneToOne(mappedBy = "association2", fetch = FetchType.LAZY)
|
||||
private EntityB mappedAssociation2;
|
||||
|
||||
protected EntityA() {
|
||||
}
|
||||
|
||||
public EntityA(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public EntityA getSelfAssociation() {
|
||||
return selfAssociation;
|
||||
}
|
||||
|
||||
public void setSelfAssociation(EntityA selfAssociation) {
|
||||
this.selfAssociation = selfAssociation;
|
||||
}
|
||||
|
||||
public EntityA getMappedSelfAssociation() {
|
||||
return mappedSelfAssociation;
|
||||
}
|
||||
|
||||
public void setMappedSelfAssociation(EntityA mappedSelfAssociation) {
|
||||
this.mappedSelfAssociation = mappedSelfAssociation;
|
||||
}
|
||||
|
||||
public EntityB getMappedAssociation1() {
|
||||
return mappedAssociation1;
|
||||
}
|
||||
|
||||
public void setMappedAssociation1(EntityB mappedAssociation1) {
|
||||
this.mappedAssociation1 = mappedAssociation1;
|
||||
}
|
||||
|
||||
public EntityB getMappedAssociation2() {
|
||||
return mappedAssociation2;
|
||||
}
|
||||
|
||||
public void setMappedAssociation2(EntityB mappedAssociation2) {
|
||||
this.mappedAssociation2 = mappedAssociation2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "entityb")
|
||||
public static class EntityB {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@OneToOne
|
||||
private EntityA association1;
|
||||
|
||||
@OneToOne
|
||||
private EntityA association2;
|
||||
|
||||
protected EntityB() {
|
||||
}
|
||||
|
||||
public EntityB(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public EntityA getAssociation1() {
|
||||
return association1;
|
||||
}
|
||||
|
||||
public void setAssociation1(EntityA association1) {
|
||||
this.association1 = association1;
|
||||
}
|
||||
|
||||
public EntityA getAssociation2() {
|
||||
return association2;
|
||||
}
|
||||
|
||||
public void setAssociation2(EntityA association2) {
|
||||
this.association2 = association2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue