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

JPA projection query returning single non-standard JPA type results in "No aliases found in result tuple" error [DATAJPA-984] #1330

Closed
spring-projects-issues opened this issue Oct 20, 2016 · 7 comments
Assignees
Labels
in: core type: bug

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Oct 20, 2016

Joris Kuipers opened DATAJPA-984 and commented

This relates directly to DATAJPA-885. The issue described there still occurs when a query returns a standard JPA projection consisting of a single type, where Spring Data JPA doesn't recognize that the type can be mapped by the JPA provider itself. In my case this happens when returning a collection of Joda LocalDate instances.

I've attached a small sample app with a unit test that shows the problem. The same test also shows that a direct JPA query does work.

It would be nice if Spring Data JPA could somehow detect that I'm not trying to use its projection feature in this case, to prevent the "No aliases found in result tuple" error from happening.


Affects: 1.10.4 (Hopper SR4)

Attachments:

Issue Links:

Referenced from: commits fc07367, 63c0099

Backported to: 1.10.5 (Hopper SR5)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Oct 21, 2016

Oliver Drotbohm commented

This is fixed in master and the bugfix branch for Hopper. Your sample project works fine with the latest snapshots

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Oct 21, 2016

Joris Kuipers commented

Thanks for the quick fix, Oliver!

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 12, 2016

Pál Hebők commented

The error still exists when querrying empty tables for single results (e.g.: trying find the oldest person's birthday, so querrying for the min value and the table has no rows).

Updates I made to the repository:

package com.example;

import java.util.List;

import org.joda.time.LocalDate;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface PersonRepository extends JpaRepository<Person, Long> {
    @Query("select distinct p.birthDate from Person p order by p.birthDate")
    List<LocalDate> findAllBirthDates();

    @Query("select min(p.birthDate) from Person p")
    LocalDate findMinBirthDate();
}

And the test cases:

package com.example;

import java.util.Arrays;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.joda.time.LocalDate;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProjectionbugApplicationTests {

    @Autowired
    PersonRepository personRepository;
    @PersistenceContext
    EntityManager em;

    @Before
    public void setUp() {
        personRepository.save(Arrays.asList(new Person(new LocalDate(1976, 7, 15), "Joris"), new Person(new LocalDate(1978, 2, 19), "Sander")));
        personRepository.deleteAll();
    }

    @Test
    public void findAllBirthDates() {
        List<LocalDate> birthDates = personRepository.findAllBirthDates();
        Assert.assertEquals(0, birthDates.size());
    }

    @Test
    public void findAllBirthDatesNativeJpa() {
        List<LocalDate> birthDates = em.createQuery("select distinct p.birthDate from Person p order by p.birthDate", LocalDate.class).getResultList();
        Assert.assertEquals(0, birthDates.size());
    }

    @Test
    public void findMinBirthDate() {
        LocalDate birthDate = personRepository.findMinBirthDate();
        Assert.assertNull(birthDate);
    }

    @Test
    public void findMinBirthDateNativeJpa() {
        LocalDate birthDate = em.createQuery("select min(p.birthDate) from Person p", LocalDate.class).getSingleResult();
        Assert.assertNull(birthDate);
    }

}

Stacktrace from the sample project:

org.springframework.dao.InvalidDataAccessApiUsageException: No aliases found in result tuple! Make sure your query defines aliases!; nested exception is java.lang.IllegalStateException: No aliases found in result tuple! Make sure your query defines aliases!
	at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381)
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)
	at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
	at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy70.findMinBirthDate(Unknown Source)
	at com.example.ProjectionbugApplicationTests.findMinBirthDate(ProjectionbugApplicationTests.java:47)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalStateException: No aliases found in result tuple! Make sure your query defines aliases!
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter.convert(AbstractJpaQuery.java:258)
	at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:212)
	at org.springframework.data.repository.query.ResultProcessor$ChainingConverter$1.convert(ResultProcessor.java:200)
	at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:212)
	at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:159)
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:119)
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:104)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:482)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
	... 38 more

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 13, 2016

Oliver Drotbohm commented

Did you upgrade the sample to 1.10.5? The line numbers indicate you'r still using the old version as AbstractJpaQuery:258 is where the exception was thrown before the handling of the individual elements was added. The exception is now thrown from line 282. Care to provide a test case that reproduces the issue? I don't want to copy stuff over from your post and potentially miss something, especially as there are indications you're not even using the fixed version

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 13, 2016

Pál Hebők commented

I did forget to update project dependencies, thanks for the heads up. I was originally planning to attach the update project in a zip, but I don't have the option to attach files, so here's a git repository instead: https://github.com/PaulDaPigeon/PossibleSpringDataBug
Hope this can help you work things out

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 13, 2016

Oliver Drotbohm commented

Hm, for whatever reason Hibernate returns a Tuple containing a null element here instead of null in the first place. Would you mind filing a new ticket as this one is already closed and thus showing up in changelogs as fixed. The fix itself is trivial and shouldn't take long to push

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 13, 2016

Pál Hebők commented

Ticket filed as requested. DATAJPA-1024
Thanks for the quick replies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core type: bug
Projects
None yet
Development

No branches or pull requests

2 participants