it-swarm.com.ru

Исключение "Получен другой размер кортежей и псевдонимов" после перехода на Spring Boot 2.0.0.RELEASE

//imports, etc.

@Entity
@Table(name = "TSTRANS")
@SqlResultSetMappings(
        {                   
                @SqlResultSetMapping(name = TS_TRANS_EMP_STAT,
                        classes = {
                                @ConstructorResult(
                                        targetClass = EmpStat.class,
                                        columns = {
                                                @ColumnResult(name = "EMPID", type = Long.class),
                                                @ColumnResult(name = "CODE", type = String.class),
                                                @ColumnResult(name = "TOTALCOUNT", type = Integer.class)
                                        }
                                )
                        })
        }
)
@NamedNativeQueries({
        @NamedNativeQuery(name = "TsTrans.getStat", query = "select * from SP_TASK_STATS_EMP  (:in_empid, :in_gidstr, :in_onlytodo)", resultSetMapping = TS_TRANS_EMP_STAT)
})
public class TsTrans extends TsTransCommon {
    public static final String TSTRANS_BADGE = "TSTRANS_BADGE";

    private static final long serialVersionUID = -3391028108003625153L;
    public static final String TS_TRANS_EMP_STAT = "TsTrans.empStat";
    public static final String TS_TRANS_SCHEDULE_STAT = "TsTrans.getScheduleStat";
    public static final String TS_TRANS_FOLLOWUP = "TS_TRANS_FOLLOWUP";
}

Это сущность.

// imports, etc.

public class EmpStat extends BaseStat {

    private static final long serialVersionUID = -4410895509438727581L;
    private Long mEmpid;

    public EmpStat(Long aEmpid, String aCode, Integer aTotalcount) {
        super(aCode, aTotalcount);
        mEmpid = aEmpid;
    }

    public Long getEmpid() {
        return mEmpid;
    }

    public void setEmpid(Long aEmpid) {
        mEmpid = aEmpid;
    }
}

Это не-сущность pojo, возвращаемый тип namedquery.

// imports, etc.

@Repository
public interface TsTransRepository extends TsTransCommonRepository<TsTrans> {
    List<EmpStat> getStat(@Param("in_empid") Long aEmpid, @Param("in_gidstr") String aGidstr, @Param("in_onlytodo") Boolean aOnlytodo);

}

Это класс репозитория.

Я использую это namednativequeries чтобы возвращать не-сущности pojos из хранимых процедур. Работает без исключения с Spring Boot 1.5.9. И на Spring Boot 2.0.0.M7. После перехода на 2.0.0.RELEASE возникло следующее исключение.

org.hibernate.HibernateException: Got different size of tuples and aliases
    at org.hibernate.jpa.spi.NativeQueryTupleTransformer$NativeTupleImpl.<init>(NativeQueryTupleTransformer.Java:68) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.jpa.spi.NativeQueryTupleTransformer.transformTuple(NativeQueryTupleTransformer.Java:28) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.Java:85) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.Java:430) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.Java:2507) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.loader.Loader.list(Loader.Java:2502) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.Java:335) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.Java:2161) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.Java:1016) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.Java:152) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.Java:1414) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.query.Query.getResultList(Query.Java:146) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.Java:129) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.Java:91) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.Java:136) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.Java:125) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.Java:590) ~[spring-data-commons-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.Java:578) ~[spring-data-commons-2.0.5.RELEASE.jar:2.0.5.RELEASE]

Я что-то упустил во время миграции?

12
evracle

В jpa 2.1, добавив аннотацию @Query(nativeQuery = true) к методу интерфейса репозитория, исправлена ​​ошибка . Ссылка:

https://github.com/spring-projects/spring-data-examples/tree/master/jpa/jpa21#support-for-custom-sqlresultsetmapping-with-constructorresult

10
evracle

Измените SqlResultSetMappings на 

@SqlResultSetMappings({
    @SqlResultSetMapping(name = TS_TRANS_EMP_STAT,
        columns = {
            @ColumnResult(name = "EMPID", type = Long.class),
            @ColumnResult(name = "CODE", type = String.class),
            @ColumnResult(name = "TOTALCOUNT", type = Integer.class)
        })
}

и измените EmpStat с обычного класса на интерфейс:

public interface EmpStat {
    Long getEMPID();
    String getCODE();
    Integer getTOTALCOUNT();
}
7
Songday

Я нашел еще одно решение: вы можете просто удалить generic из List в getStat ():

@Repository
public interface TsTransRepository extends TsTransCommonRepository<TsTrans> {
    List getStat(@Param("in_empid") Long aEmpid, @Param("in_gidstr") String aGidstr, @Param("in_onlytodo") Boolean aOnlytodo);
}
6
Igor Zboichik

Есть несколько подходов, как это исправить, в основном это сочетание различных функций данных jpa и spring. Я провел некоторые расследования и добавил их для выпуска https://jira.spring.io/browse/DATAJPA-1280 . Чтобы найти то, что вы могли бы сделать, пожалуйста, посмотрите на этот проект https://github.com/EugeneNik/spring-data-datajpa-1280-example и запустите тесты, чтобы увидеть, какие подходы работают нормально сейчас. Обратите внимание, что в настоящее время нет способа выполнить миграцию без изменений кода, но, на мой взгляд, самый простой способ - добавить объявление проекции класса в метод репозитория. Определив его, вы не должны менять все отображения, но также должны быть изменены и обращения к репозиториям. Это просто еще один способ решить вашу проблему:

@Repository
public interface TsTransRepository extends TsTransCommonRepository<TsTrans> 
{
    <T> List<T> getStat(@Param("in_empid") Long aEmpid, 
@Param("in_gidstr") String aGidstr, @Param("in_onlytodo") Boolean aOnlytodo, Class<T> beanProjection);

}

Я думаю, что это отчет о проблемах в Spring Data JPA: https://jira.spring.io/browse/DATAJPA-1280

В качестве обходного пути вы можете перейти к версии выпуска данных Spring Kay-SR4 (SR5 - это последняя последняя версия и версия, используемая в Spring Boot 2.0.0). Просто добавь:

<spring-data-releasetrain.version>Kay-SR4</spring-data-releasetrain.version>

в раздел <properties> вашего pom.xml.

1
candrews

Как отмечали другие, это была ошибка, появившаяся в Spring Boot 2.0.0 и сообщавшаяся в DATAJPA-1280 .

Это было исправлено и выпущено в Spring Boot 2.0.3.

0
Sean Connolly