You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DTO与JRXML创建Jasper Report交叉表遇类型转换错误求助

问题解决:Jasper交叉表动态列实现与ClassCastException修复

错误原因分析

你遇到的ClassCastException: java.util.ArrayList cannot be cast to java.lang.Comparable是因为:

  • 交叉表的分组桶(bucket)要求元素必须实现Comparable接口,用于分组排序,但你在列组的bucket表达式中直接使用了$F{chargeCode}(List<String>类型),ArrayList并未实现Comparable,导致排序时类型转换失败。
  • 同时,当前的MyDTO结构(一个job对应多个chargeCode和金额的列表)不符合交叉表的数据源要求:交叉表需要扁平化的原子数据(每行对应一个job、一个chargeCode、一个金额),而非嵌套列表结构。

解决方案

1. 调整数据源DTO结构

将嵌套的MyDTO转换为扁平化的DTO,每个实例对应一条job+chargeCode+金额的记录:

class FlatChargeDTO {
    private String jobNo;
    private String chargeCode;
    private BigDecimal chargeAmount;

    // 构造方法、getter/setter省略
}

转换示例(将原MyDTO列表转成FlatChargeDTO列表):

List<FlatChargeDTO> flatData = new ArrayList<>();
for (MyDTO dto : originalMyDTOList) {
    String jobNo = dto.getJobNo();
    List<String> codes = dto.getChargeCode();
    List<BigDecimal> amounts = dto.getChargeCodeTotal();
    for (int i = 0; i < codes.size(); i++) {
        flatData.add(new FlatChargeDTO(jobNo, codes.get(i), amounts.get(i)));
    }
}

2. 修改JRXML交叉表配置

调整字段、分组桶和度量的配置,适配扁平化数据源:

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
              name="vendorBillingCompletedJobReport" leftMargin="5" rightMargin="5">

    <!-- 定义扁平化数据源的字段 -->
    <field name="jobNo" class="java.lang.String"/>
    <field name="chargeCode" class="java.lang.String"/>
    <field name="chargeAmount" class="java.math.BigDecimal"/>

    <summary>
        <band height="60">
            <crosstab>
                <reportElement width="782" y="0" x="0" height="60"/>
                
                <!-- 行组:按jobNo分组 -->
                <rowGroup name="jobNoGroup" width="100" totalPosition="End">
                    <bucket>
                        <bucketExpression class="java.lang.String">
                            <![CDATA[$F{jobNo}]]>
                        </bucketExpression>
                    </bucket>
                    <crosstabRowHeader>
                        <cellContents>
                            <box>
                                <pen lineColor="black" lineWidth="1"/>
                            </box>
                            <textField>
                                <reportElement width="100" y="0" x="0" height="20"/>
                                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                                <textFieldExpression><![CDATA[$V{jobNoGroup}]]></textFieldExpression>
                            </textField>
                        </cellContents>
                    </crosstabRowHeader>
                    <crosstabTotalRowHeader>
                        <cellContents>
                            <box>
                                <pen lineColor="black" lineWidth="1"/>
                            </box>
                            <staticText>
                                <reportElement x="0" y="0" width="100" height="20"/>
                                <textElement verticalAlignment="Middle" textAlignment="Center"/>
                                <text>TOTAL</text>
                            </staticText>
                        </cellContents>
                    </crosstabTotalRowHeader>
                </rowGroup>

                <!-- 列组:按chargeCode动态生成列 -->
                <columnGroup name="chargeCodeGroup" height="20" totalPosition="End">
                    <bucket>
                        <bucketExpression class="java.lang.String">
                            <![CDATA[$F{chargeCode}]]>
                        </bucketExpression>
                    </bucket>
                    <crosstabColumnHeader>
                        <cellContents>
                            <box>
                                <pen lineColor="black" lineWidth="1"/>
                            </box>
                            <textField isStretchWithOverflow="true">
                                <reportElement width="120" y="0" x="0" height="20"/>
                                <textElement verticalAlignment="Middle" textAlignment="Center"/>
                                <textFieldExpression><![CDATA[$V{chargeCodeGroup}]]></textFieldExpression>
                            </textField>
                        </cellContents>
                    </crosstabColumnHeader>
                    <crosstabTotalColumnHeader>
                        <cellContents>
                            <box>
                                <pen lineColor="black" lineWidth="1"/>
                            </box>
                            <staticText>
                                <reportElement width="120" y="0" x="0" height="20"/>
                                <textElement verticalAlignment="Middle" textAlignment="Center"/>
                                <text>TOTAL</text>
                            </staticText>
                        </cellContents>
                    </crosstabTotalColumnHeader>
                </columnGroup>

                <!-- 度量:计算金额总和 -->
                <measure name="totalAmount" class="java.math.BigDecimal" calculation="Sum">
                    <measureExpression><![CDATA[$F{chargeAmount}]]></measureExpression>
                </measure>

                <!-- 交叉表单元格:显示金额 -->
                <crosstabCell height="20" width="120">
                    <cellContents backcolor="#FFFFFF">
                        <box>
                            <pen lineColor="black" lineWidth="1"/>
                        </box>
                        <textField>
                            <reportElement x="5" y="0" width="115" height="20"/>
                            <textElement textAlignment="Right" verticalAlignment="Middle"/>
                            <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{totalAmount}]]></textFieldExpression>
                            <pattern>#,##0.00</pattern>
                        </textField>
                    </cellContents>
                </crosstabCell>

                <!-- 总计单元格样式 -->
                <crosstabCell height="20" width="120" rowTotal="true">
                    <cellContents backcolor="#F0F0F0">
                        <box>
                            <pen lineColor="black" lineWidth="1"/>
                        </box>
                        <textField>
                            <reportElement x="5" y="0" width="115" height="20"/>
                            <textElement textAlignment="Right" verticalAlignment="Middle"/>
                            <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{totalAmount}]]></textFieldExpression>
                            <pattern>#,##0.00</pattern>
                        </textField>
                    </cellContents>
                </crosstabCell>
                <crosstabCell height="20" width="100" columnTotal="true">
                    <cellContents backcolor="#F0F0F0">
                        <box>
                            <pen lineColor="black" lineWidth="1"/>
                        </box>
                        <textField>
                            <reportElement x="5" y="0" width="95" height="20"/>
                            <textElement textAlignment="Right" verticalAlignment="Middle"/>
                            <textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{totalAmount}]]></textFieldExpression>
                            <pattern>#,##0.00</pattern>
                        </textField>
                    </cellContents>
                </crosstabCell>
            </crosstab>
        </band>
    </summary>
</jasperReport>

关键调整说明

  • 将行组和列组的bucket表达式改为String类型(jobNo和chargeCode),它们天然实现Comparable,解决类型转换错误。
  • 使用扁平化的FlatChargeDTO作为数据源,让交叉表能正确按job和chargeCode分组,并聚合计算金额。
  • 增加了金额格式化的pattern,优化显示效果,同时配置了总计单元格的背景色区分。

内容的提问来源于stack exchange,提问作者ATWonder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:08:31