java.lang.ClassCastException:[B不能强制转换为[Ljava.lang.Object;在使用JPA 2.2 query.getResultStreamfindFirst时

问题描述

我的Spring Data存储库方法代码如下:

public Optional<byte[]> findShipmentLabelByClientIdAndAwb(String clientId,String awb) {

    String queryString = "select g.shipmentLabel as shipmentLabel from GenericShipment g where g.client.id = :clientId and g.shipmentId = :awb " +
        " AND (g.processingStatus is null or g.processingStatus <> 'DELETED') AND g.shipmentLabel is not null";

    val query = entityManager.createquery(queryString,byte[].class);

    query.setParameter("clientId",clientId);
    query.setParameter("awb",awb);

    return query.getResultStream().findFirst();

}

如您所见,我试图获取 shipmentLabel 列(在我的Postgres模式中定义为 bytea )作为字节数组。 运行时会发生以下异常:

java.lang.classCastException:[无法将B强制转换为[Ljava.lang.Object ; 在org.hibernate.internal.ScrollableResultsImpl.prepareCurrentRow(ScrollableResultsImpl.java:203) 在org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:101) 在org.hibernate.query.internal.ScrollableResultsIterator.hasNext(ScrollableResultsIterator.java:33) 在java.util.Spliterators $ IteratorSpliterator.tryAdvance(Spliterators.java:1811) 在java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) 在java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499) 在java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486) 在java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:472) 在java.util.stream.FindOps $ FindOp.evaluateSequential(FindOps.java:152) 在java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 在java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:531) 在 org.hibernate.query.spi.StreamDecorator.findFirst(StreamDecorator.java:260)

我想知道这是否是预期的行为,在此先感谢您的回答。

目前,解决方法是使用JPA 2.1变体:

返回query.getResultList()。stream()。findFirst();

作为环境,我正在使用 Spring Boot 2.3.3 休眠版本是 5.4.20

解决方法

首先尝试使用getResultList,然后查看是否有效:

public Optional<Byte[]> findShipmentLabelByClientIdAndAwb(
        String clientId,String awb) {
    return entityManager.createQuery("""
        select 
            g.shipmentLabel as shipmentLabel 
        from GenericShipment g 
        where 
            g.client.id = :clientId and 
            g.shipmentId = :awb and 
            (
                g.processingStatus is null or 
                g.processingStatus <> 'DELETED'
            ) and 
            g.shipmentLabel is not null
        """)
    .setParameter("clientId",clientId)
    .setParameter("awb",awb)
    .setMaxResults(1)
    .getResultList()
    .stream()
    .findFirst();
}

请注意,仅使用fidFirst仅选择N条记录作为第一条记录是没有效率的。如果该查询返回100条记录怎么办?您仍然需要从数据库中选择所有100个。

这就是为什么我添加了setMaxResults呼叫的原因。

如果这不起作用,请尝试调试Hibernate BinaryType,并查看为什么它不返回byte[]

,

没有用于字节的原始流,您可以在调试器中检查可能正在使用Stream<Byte[]>Stream<Object[]>的哪种类型的流。这可以解释您遇到的异常。使用Byte []应该可以解决您的问题。

public Optional<Byte[]> findShipmentLabelByClientIdAndAwb(String clientId,String awb) {
    String queryString = "select g.shipmentLabel as shipmentLabel from GenericShipment g where g.client.id = :clientId and g.shipmentId = :awb " +
        " AND (g.processingStatus is null or g.processingStatus <> 'DELETED') AND g.shipmentLabel is not null";

     val query = entityManager.createQuery(queryString,Byte[].class);

     query.setParameter("clientId",clientId);
     query.setParameter("awb",awb);

     return query.getResultStream().findFirst();

}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...