简体   繁体   中英

“Got different size of tuples and aliases” exception after Spring Boot 2.0.0.RELEASE migration

//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";
}

This is the entity.

// 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;
    }
}

This is the non-entity pojo, namedquery return type.

// 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);

}

This is the repository class.

I'm using this namednativequeries to return non-entity pojos from stored procedures. It's been working without exception since Spring Boot 1.5.9. And on Spring Boot 2.0.0.M7. After migration to 2.0.0.RELEASE , the following exception started to occur.

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]

Did I miss something, during migration?

In jpa 2.1 putting @Query(nativeQuery = true) annotation on the repository interface method, fixed the issue. Reference:

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

Change your SqlResultSetMappings to

@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)
        })
}

and change EmpStat from normal class to interface:

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

I've found one more solution: you can just remove generic from List in 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);
}

There are several approaches how to fix it, mostly it is combination of different jpa and spring data features. I made some investigations and added them to issue https://jira.spring.io/browse/DATAJPA-1280 . To find what you could do, please look at this project https://github.com/EugeneNik/spring-data-datajpa-1280-example and run tests to see what approaches are working fine now. Note, currently there are no way to do migration without code changes, but to my mind the simpliest way is to add class projection declaration to your repository method. Defining it you have not to change all mappings, but repositories invocations have to been changed as well. It's just another way to fix your problem:

@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);

}

It was a bug, now fixed: jira.spring.io/browse/DATAJPA-1280

Add:

@Query(nativeQuery=true) 

at the top of a new method in the repository.

I think this is the issue report in Spring Data JPA: https://jira.spring.io/browse/DATAJPA-1280

As a workaround, you can downgrade to Spring Data release train Kay-SR4 (SR5 is the current latest version and is the version used in Spring Boot 2.0.0). Just add:

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

to your pom.xml's <properties> section.

As others noted, this was a bug introduced in Spring Boot 2.0.0 and reported in DATAJPA-1280 .

It has been fixed and released in Spring Boot 2.0.3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM