Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native Queries throwing LazyInitializationException for EAGER fetches after upgrading to version 3 #2780

Closed
rozagerardo opened this issue Jan 28, 2023 · 4 comments
Labels
for: external-project For an external project and not something we can fix

Comments

@rozagerardo
Copy link

rozagerardo commented Jan 28, 2023

I have the following Entity:

@Entity
public class Foo {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	private String name;

	@ManyToOne(optional = false)
	private Bar bar;

       // ... constructors, getters, setters, equals, and hashcode implementations ...

Note: @ManyToOne's fetch attribute defaults to FetchType.EAGER. The issue is also present if I set it explicitly.

This is the Spring Data JPA Repository I'm using, that contains two similar queries, one using JPQL and the other using a native query:

public interface FooRepository extends CrudRepository<Foo, Long> {

	@Query("select f from Foo f order by f.name desc")
	List<Foo> allFoosSortedByName();

	@Query(value = "select * from Foo f order by f.name desc", nativeQuery = true)
	List<Foo> allFoosSortedByNameNative();

}

This is the main application class from where I call these methods:

@SpringBootApplication
public class MyApp implements ApplicationRunner {

	private static final Logger LOG = LoggerFactory.getLogger(MyApp.class);

	@Autowired
	private FooRepository fooRepository;

	public static void main(final String... args) {
		SpringApplication.run(MyApp.class, args);
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {

		List<Foo> customQueryResults = fooRepository.allFoosSortedByName();
		LOG.info("All Foos sorted by name descending order:");
		customQueryResults.forEach(t -> LOG.info("{}", t));

		List<Foo> nativeQueryFoosSortedByDueDateDescResults = fooRepository.allFoosSortedByNameNative();
		LOG.info("All Foos sorted by name descending order with native query:");
		nativeQueryFoosSortedByDueDateDescResults.forEach(t -> LOG.info("{}", t));

	}
}

This functionality was working fine, but after upgrading to Boot 3 (which implies using Spring Data 3), the native query doesn't correctly log Foo entries, because the Bar association has not been fetched Eagerly as established by the relationship.

This is the log output for the first query (I have added the spring.jpa.show-sql=true Boot property to clearly see the queries the framework is performing on the logs):

 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :Started MyApp in 1.685 seconds (process running for 1.857)
Hibernate: select f1_0.id,f1_0.bar_id,f1_0.name from foo f1_0 order by f1_0.name desc
Hibernate: select b1_0.id,b1_0.code,b1_0.description,b1_0.name,t1_0.bar_id,t1_0.id,t1_0.name from bar b1_0 left join foo t1_0 on b1_0.id=t1_0.bar_id where b1_0.id=?
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :All Foos sorted by name descending order:
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :Foo [id=3, name=Foo 3, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :Foo [id=2, name=Foo 2, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :Foo [id=1, name=Foo 1, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]

but the second one (the native one) is logging the following INFO (?) console messages:

Hibernate: select * from Foo f order by f.name desc
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :All Foos sorted by name descending order with native query:
SLF4J: Failed toString() invocation on an object of type [com.ger.lsd.persistence.model.Foo]
Reported exception:
org.hibernate.LazyInitializationException: could not initialize proxy [com.ger.lsd.persistence.model.Bar#1] - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
	at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:44)
	at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:102)
	at com.ger.lsd.persistence.model.Bar$HibernateProxy$sn60O2sK.toString(Unknown Source)
	at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453)
	at com.ger.lsd.persistence.model.Foo.toString(Foo.java:62)
	at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:291)
	at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:263)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:225)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:160)
	at ch.qos.logback.classic.spi.LoggingEvent.getFormattedMessage(LoggingEvent.java:397)
	at ch.qos.logback.classic.spi.LoggingEvent.prepareForDeferredProcessing(LoggingEvent.java:253)
	at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:226)
	at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_1(Logger.java:402)
	at ch.qos.logback.classic.Logger.info(Logger.java:588)
	at com.ger.lsd.MyApp.lambda$run$1(MyApp.java:38)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at com.ger.lsd.MyApp.run(MyApp.java:38)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:758)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:748)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
	at com.ger.lsd.MyApp.main(MyApp.java:26)
 INFO 6569 ---[           main] com.ger.lsd.MyApp                   :[FAILED toString()]
...

With the 2.x version, my application was correctly fetching the associated Bar association eagerly as you can appreciate in the following logs:

Hibernate: select * from Foo f order by f.name desc
Hibernate: select bar0_.id as id1_0_0_, bar0_.code as code2_0_0_, bar0_.description as descript3_0_0_, bar0_.name as name4_0_0_, foos1_.bar_id as bar_id3_1_1_, foos1_.id as id1_1_1_, foos1_.id as id1_1_2_, foos1_.bar_id as bar_id3_1_2_, foos1_.name as name2_1_2_ from bar bar0_ left outer join foo foos1_ on bar0_.id=foos1_.bar_id where bar0_.id=?
 INFO 6837 ---[           main] com.ger.lsd.MyApp                   :All Foos sorted by name descending order with native query:
 INFO 6837 ---[           main] com.ger.lsd.MyApp                   :Foo [id=3, name=Foo 3, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]
 INFO 6837 ---[           main] com.ger.lsd.MyApp                   :Foo [id=2, name=Foo 2, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]
 INFO 6837 ---[           main] com.ger.lsd.MyApp                   :Foo [id=1, name=Foo 1, description=, dueDate=, status=, bar=Bar [id=1, code=P1, name=Bar 1, description=Description of Bar 1], assignee=]

I couldn't find any relevant information that could guide me here in the 'Spring Data 2022.0 (Turing) Release Notes' docs

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 28, 2023
@schauder
Copy link
Contributor

This sounds very much like a Hibernate issue, since all the JPA mapping is done by it.
I recommend creating a reproducer based purely on Hibernate and submitting an issue with them.

If you think this is actually a Spring Data issue, please provide a reproducer for the issue including a test case that demonstrates the correct behaviour using the EntityManager directly.

@schauder schauder added for: external-project For an external project and not something we can fix status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 30, 2023
@spring-projects-issues
Copy link

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Feb 6, 2023
@spring-projects-issues
Copy link

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@spring-projects-issues spring-projects-issues closed this as not planned Won't fix, can't repro, duplicate, stale Feb 13, 2023
@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue labels Feb 13, 2023
@rozagerardo
Copy link
Author

Sorry for the delay here.
Just for visibility, you were right @schauder , this is a hibernate issue:

https://hibernate.atlassian.net/browse/HHH-16191

thanks for the heads up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

3 participants