HHH-12484 - Improved error output for LazyInitializationException to include entity-related info

This commit is contained in:
nikowitt 2018-04-16 07:55:40 +02:00 committed by Vlad Mihalcea
parent 0423dd6777
commit 833f6b50a4
2 changed files with 197 additions and 11 deletions

View File

@ -152,13 +152,13 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
permissiveInitialization();
}
else if ( session == null ) {
throw new LazyInitializationException( "could not initialize proxy - no Session" );
throw new LazyInitializationException( "could not initialize proxy [" + entityName + "#" + id + "] - no Session" );
}
else if ( !session.isOpen() ) {
throw new LazyInitializationException( "could not initialize proxy - the owning Session was closed" );
throw new LazyInitializationException( "could not initialize proxy [" + entityName + "#" + id + "] - the owning Session was closed" );
}
else if ( !session.isConnected() ) {
throw new LazyInitializationException( "could not initialize proxy - the owning Session is disconnected" );
throw new LazyInitializationException( "could not initialize proxy [" + entityName + "#" + id + "] - the owning Session is disconnected" );
}
else {
target = session.immediateLoad( entityName, id );
@ -175,7 +175,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
if ( session == null ) {
//we have a detached collection thats set to null, reattach
if ( sessionFactoryUuid == null ) {
throw new LazyInitializationException( "could not initialize proxy - no Session" );
throw new LazyInitializationException( "could not initialize proxy [" + entityName + "#" + id + "] - no Session" );
}
try {
SessionFactoryImplementor sf = (SessionFactoryImplementor)
@ -214,7 +214,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
}
}
catch (Exception e) {
log.error( "Initialization failure", e );
log.error( "Initialization failure [" + entityName + "#" + id + "]", e );
throw new LazyInitializationException( e.getMessage() );
}
}
@ -224,7 +224,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
checkTargetState(session);
}
else {
throw new LazyInitializationException( "could not initialize proxy - Session was closed or disced" );
throw new LazyInitializationException( "could not initialize proxy [" + entityName + "#" + id + "] - Session was closed or disced" );
}
}
@ -300,12 +300,12 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
private void errorIfReadOnlySettingNotAvailable() {
if ( session == null ) {
throw new TransientObjectException(
"Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
"Proxy [" + entityName + "#" + id + "] is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
);
}
if ( session.isClosed() ) {
throw new SessionException(
"Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session."
"Session is closed. The read-only/modifiable setting is only accessible when the proxy [" + entityName + "#" + id + "] is associated with an open session."
);
}
}
@ -323,7 +323,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
if ( this.readOnly != readOnly ) {
final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
if ( !persister.isMutable() && !readOnly ) {
throw new IllegalStateException( "cannot make proxies for immutable entities modifiable" );
throw new IllegalStateException( "cannot make proxies [" + entityName + "#" + id + "] for immutable entities modifiable" );
}
this.readOnly = readOnly;
if ( initialized ) {
@ -351,7 +351,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
protected final Boolean isReadOnlyBeforeAttachedToSession() {
if ( isReadOnlySettingAvailable() ) {
throw new IllegalStateException(
"Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
"Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true [" + entityName + "#" + id + "]"
);
}
return readOnlyBeforeAttachedToSession;
@ -373,7 +373,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
final void setReadOnlyBeforeAttachedToSession(Boolean readOnlyBeforeAttachedToSession) {
if ( isReadOnlySettingAvailable() ) {
throw new IllegalStateException(
"Cannot call setReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
"Cannot call setReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true [" + entityName + "#" + id + "]"
);
}
this.readOnlyBeforeAttachedToSession = readOnlyBeforeAttachedToSession;

View File

@ -0,0 +1,186 @@
/*
* 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.test.lazyload;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import org.hibernate.LazyInitializationException;
import org.hibernate.internal.AbstractSharedSessionContract;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* @author Vlad Mihalcea
*/
public class LazyLoadingLoggingTest
extends BaseCoreFunctionalTestCase {
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Client.class,
Address.class
};
}
@Override
protected void afterSessionFactoryBuilt() {
doInHibernate( this::sessionFactory, session -> {
Address address = new Address();
address.setId( 1L );
address.setStreet( "Marea albastra" );
session.persist( address );
Client client = new Client();
client.setId( 1L );
client.setName( "Dorian" );
client.setAddress( address );
session.persist( client );
} );
}
@Test
@TestForIssue(jiraKey = "HHH-12484")
public void testNoSession() {
Address address = doInHibernate( this::sessionFactory, s -> {
return s.load( Address.class, 1L );
} );
try {
address.getClient().getName();
fail( "Should throw LazyInitializationException" );
}
catch (LazyInitializationException expected) {
assertEquals(
"could not initialize proxy " +
"[org.hibernate.test.lazyload.LazyLoadingLoggingTest$Address#1] " +
"- no Session",
expected.getMessage()
);
}
}
@Test
@TestForIssue(jiraKey = "HHH-12484")
public void testDisconnect() {
doInHibernate( this::sessionFactory, session -> {
Address address = session.load( Address.class, 1L );
AbstractSharedSessionContract sessionContract = (AbstractSharedSessionContract) session;
sessionContract.getJdbcCoordinator().close();
try {
address.getClient().getName();
fail( "Should throw LazyInitializationException" );
}
catch (LazyInitializationException expected) {
assertEquals(
"could not initialize proxy " +
"[org.hibernate.test.lazyload.LazyLoadingLoggingTest$Address#1] " +
"- the owning Session is disconnected",
expected.getMessage()
);
}
session.getTransaction().markRollbackOnly();
} );
}
protected boolean rebuildSessionFactoryOnError() {
return false;
}
@Entity(name = "Address")
public static class Address {
@Id
private Long id;
@Column
private String street;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_client")
private Client client;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
}
@Entity(name = "Client")
public static class Client {
@Id
private Long id;
@Column
private String name;
@OneToOne(mappedBy = "client", fetch = FetchType.LAZY)
private Address address;
public Client() {
}
public void setName(String name) {
this.name = name;
}
public Client(Address address) {
this.address = address;
address.setClient( this );
}
public String getName() {
return name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
}