簡體   English   中英

java.lang.ClassCastException: [B 不能轉換為 [Ljava.lang.Object; 使用 JPA 2.2 query.getResultStream().findFirst()

[英]java.lang.ClassCastException: [B cannot be cast to [Ljava.lang.Object; while using JPA 2.2 query.getResultStream().findFirst()

我的 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();

}

如您所見,我正在嘗試以字節數組的形式獲取在 Postgres 架構中定義為byteashipmentLabel列。 運行時出現以下異常:

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.haseratorNext(ScrollableResultsIterator.haseratorNext(ScrollableResultsIterator) :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) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:531) at org.hibernate.query.spi。 StreamDecorator.findFirst(StreamDecorator.java:260)

我想知道這是否是這里的預期行為,在此先感謝您的回答。

目前,解決方法是使用 JPA 2.1 變體:

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

作為環境,我使用的是Spring Boot 2.3.3Hibernate版本是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();

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM