RowMapper在Java中出现无效的列名错误

huangapple go评论71阅读模式
英文:

RowMapper invalid column name error in Java

问题

I have a query and it works well on the database. However, when I tried to take them as a Java object by using RowMapper, I get an invalid column name error. I checked everything, but I don't understand the reason why this error is happening.

My query:

SELECT TEMP.SUMALLTXN, SUM(TEMP.SUMCARD), SUM(TEMP.SUMERRORTXN), SUM(TEMP.SUMERRORTXNCARD)
FROM
(SELECT
SUM(COUNT(*)) OVER() AS SUMALLTXN,

COUNT(mdmtxn.BIN) OVER (PARTITION BY mdmtxn.BIN) AS SUMCARD,

SUM(case when mdmtxn.MDSTATUS NOT IN ('1','9', '60') then 1 else 0 end) AS SUMERRORTXN,

SUM(case when mdmtxn.MDSTATUS NOT IN ('1','9', '60') then 1 else 0 end) OVER (PARTITION BY mdmtxn.BIN) AS SUMERRORTXNCARD

FROM MDM59.MDMTRANSACTION2 mdmtxn WHERE
    mdmtxn.CREATEDDATE < TO_CHAR(SYSDATE - INTERVAL ':initialMinuteParameterValue' MINUTE ,'YYYYMMDD HH24:MI:SS') AND
    mdmtxn.CREATEDDATE > TO_CHAR(SYSDATE - INTERVAL ':intervalMinuteParameterValue' MINUTE ,'YYYYMMDD HH24:MI:SS')
GROUP BY mdmtxn.MDSTATUS, mdmtxn.BIN
) TEMP
GROUP BY TEMP.SUMALLTXN

My RowMapper:

@Component
public class TotalTransactionsReportRw implements RowMapper<TotalTransactionsReportDto> {

    @Override
    public TotalTransactionsReportDto mapRow(ResultSet rs, int rowNum) throws SQLException {
        return TotalTransactionsReportDto.builder()
                .totalNumbersOfTransactions(rs.getString("SUMALLTXN"))
                .totalNumbersOfCard(rs.getString("SUMCARD"))
                .totalNumbersOfErrorTransactions(rs.getString("SUMERRORTXN"))
                .totalNumbersOfErrorCard(rs.getString("SUMERRORTXNCARD"))
                .build();
    }

    private static class TotalTransactionsDetailRwHolder {
        private static final TotalTransactionsReportRw INSTANCE = new TotalTransactionsReportRw();
    }

    public static TotalTransactionsReportRw getInstance() {
        return TotalTransactionsReportRw.TotalTransactionsDetailRwHolder.INSTANCE;
    }
}

My Dto:

@Value
@Builder
@Data
public class TotalTransactionsReportDto {
    private String totalNumbersOfTransactions;
    private String totalNumbersOfCard;
    private String totalNumbersOfErrorTransactions;
    private String totalNumbersOfErrorCard;
}

And in my tasklet class I created a list to get all data from the row mapper:

@Slf4j
@Component
@RequiredArgsConstructor
public class NotificationTasklet implements Tasklet {

    private final PofPostOfficeServiceClient pofPostOfficeServiceClient;
    private final SequenceSysGuid sequenceSysGuid;
    private final BatchProps batchProps;
    private JdbcTemplate jdbcTemplate;
    private String notificationMailSql;
    private String totalTransactionsSql;
    private String endOfHtmlString = "</table></body></html>";
    private String endOfTableString = "</table>";
    private String jobName = "vpos-notification";
    private String tdClose = "</td>";

    @Override
    public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {

        List<VposNotificationBatchDto> notificationList = getNotificationList();

        List<TotalTransactionsReportDto> totalTransactionsList = getTotalTransactionsList();

        AlertMailDto alertMailDto = createAlertMailDto(notificationList, totalTransactionsList);

        if (!(notificationList.isEmpty())) {
            sendMail(alertMailDto);
        }

        return RepeatStatus.FINISHED;
    }

    List<TotalTransactionsReportDto> getTotalTransactionsList() {
        return jdbcTemplate.query(
                totalTransactionsSql,
                new TotalTransactionsReportRw());
    }

    @Autowired
    public void setTotalTransactionsSql(@Value("classpath:sql/vposnotification/select_total_transactions_data.sql")
                                               Resource res) {
        int intervalnext = batchProps.getJobProps()
                .get(jobName).getAlertProps().getIntervalMinuteParameterValue();
        String intervalMinutes = String valueOf(intervalnext);

        int initialMinuteParameterValue = batchProps.getJobProps()
                .get(jobName).getAlertProps().getInitialMinuteParameterValue();
        String initialMinutes = String valueOf(initialMinuteParameterValue);

        this.totalTransactionsSql = SqlUtils.readSql(res);
             this.totalTransactionsSql = this.totalTransactionsSql.replace(":initialMinuteParameterValue", initialMinutes);
              this.totalTransactionsSql = this.totalTransactionsSql.replace(":intervalMinuteParameterValue", intervalMinutes);
    }

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
         this.jdbcTemplate = jdbcTemplate;
    }
}
英文:

I have a query and it works well on the database. However, when I tried to take them as a Java object by using RowMapper, I get an invalid column name error. I checked everything, but I don't understand the reason why this error happening.

My query:

SELECT TEMP.SUMALLTXN, SUM(TEMP.SUMCARD), SUM(TEMP.SUMERRORTXN), SUM(TEMP.SUMERRORTXNCARD)
FROM
(SELECT
SUM(COUNT(*)) OVER() AS SUMALLTXN,

COUNT(mdmtxn.BIN) OVER (PARTITION BY mdmtxn.BIN) AS SUMCARD,

SUM(case when mdmtxn.MDSTATUS NOT IN (&#39;1&#39;,&#39;9&#39;, &#39;60&#39;) then 1 else 0 end) AS SUMERRORTXN,

SUM(case when mdmtxn.MDSTATUS NOT IN (&#39;1&#39;,&#39;9&#39;, &#39;60&#39;) then 1 else 0 end) OVER (PARTITION BY mdmtxn.BIN) AS SUMERRORTXNCARD

FROM MDM59.MDMTRANSACTION2 mdmtxn WHERE
    mdmtxn.CREATEDDATE &lt; TO_CHAR(SYSDATE - INTERVAL &#39;:initialMinuteParameterValue&#39; MINUTE ,&#39;YYYYMMDD HH24:MI:SS&#39;) AND
    mdmtxn.CREATEDDATE &gt; TO_CHAR(SYSDATE - INTERVAL &#39;:intervalMinuteParameterValue&#39; MINUTE ,&#39;YYYYMMDD HH24:MI:SS&#39;)
GROUP BY mdmtxn.MDSTATUS, mdmtxn.BIN
) TEMP
GROUP BY TEMP.SUMALLTXN

My RowMapper:

@Component
public class TotalTransactionsReportRw implements RowMapper&lt;TotalTransactionsReportDto&gt; {

    @Override
    public TotalTransactionsReportDto mapRow(ResultSet rs, int rowNum) throws SQLException {
        return TotalTransactionsReportDto.builder()
                .totalNumbersOfTransactions(rs.getString(&quot;SUMALLTXN&quot;))
                .totalNumbersOfCard(rs.getString(&quot;SUMCARD&quot;))
                .totalNumbersOfErrorTransactions(rs.getString(&quot;SUMERRORTXN&quot;))
                .totalNumbersOfErrorCard(rs.getString(&quot;SUMERRORTXNCARD&quot;))
                .build();
    }

    private static class TotalTransactionsDetailRwHolder {
        private static final TotalTransactionsReportRw INSTANCE = new TotalTransactionsReportRw();
    }

    public static TotalTransactionsReportRw getInstance() {
        return TotalTransactionsReportRw.TotalTransactionsDetailRwHolder.INSTANCE;
    }
}

My Dto:

@Value
@Builder
@Data
public class TotalTransactionsReportDto {
    private String totalNumbersOfTransactions;
    private String totalNumbersOfCard;
    private String totalNumbersOfErrorTransactions;
    private String totalNumbersOfErrorCard;
}

And in my tasklet class I created a list to get all data from rowmapper:

@Slf4j
@Component
@RequiredArgsConstructor
public class NotificationTasklet implements Tasklet {

    private final PofPostOfficeServiceClient pofPostOfficeServiceClient;
    private final SequenceSysGuid sequenceSysGuid;
    private final BatchProps batchProps;
    private JdbcTemplate jdbcTemplate;
    private String notificationMailSql;
    private String totalTransactionsSql;
    private String endOfHtmlString = &quot;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;&quot;;
    private String endOfTableString = &quot;&lt;/table&gt;&quot;;
    private String jobName = &quot;vpos-notification&quot;;
    private String tdClose = &quot;&lt;/td&gt;&quot;;`

    @Override
    public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {

        List&lt;VposNotificationBatchDto&gt; notificationList = getNotificationList();

        List&lt;TotalTransactionsReportDto&gt; totalTransactionsList = getTotalTransactionsList();

        AlertMailDto alertMailDto = createAlertMailDto(notificationList,totalTransactionsList);

        if (!(notificationList.isEmpty())) {
            sendMail(alertMailDto);
        }

        return RepeatStatus.FINISHED;
    }

    List&lt;TotalTransactionsReportDto&gt; getTotalTransactionsList() {
        return jdbcTemplate.query(
                totalTransactionsSql,
                new TotalTransactionsReportRw());
    }

    @Autowired
    public void     setTotalTransactionsSql(@Value(&quot;classpath:sql/vposnotification/select_total_transactions_data.sql&quot;)
                                               Resource res) {
        int intervalnext = batchProps.getJobProps()
                .get(jobName).getAlertProps().getIntervalMinuteParameterValue();
        String intervalMinutes = String.valueOf(intervalnext);

        int initialMinuteParameterValue = batchProps.getJobProps()
                .get(jobName).getAlertProps().getInitialMinuteParameterValue();
        String initialMinutes = String.valueOf(initialMinuteParameterValue);

        this.totalTransactionsSql = SqlUtils.readSql(res);
             this.totalTransactionsSql = this.totalTransactionsSql.replace(&quot;:initialMinuteParameterValue&quot;,          initialMinutes);
              this.totalTransactionsSql = this.totalTransactionsSql.replace(&quot;:intervalMinuteParameterValue&quot;,     intervalMinutes);
    }

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
         this.jdbcTemplate = jdbcTemplate;
    }

答案1

得分: 0

问题在于,您的查询实际上没有列SUMCARDSUMERRORTXNSUMERRORTXNCARD。虽然有一些DBMS将SUM列与被汇总的列的名称进行别名,但Oracle不是其中之一。据我所知,Oracle将其别名为例如"SUM(SUMCARD)"或者可能是"SUM(TEMP.SUMCARD)"。然而,在我看来,这是一个不应该依赖的实现细节。

要获得您想要使用的名称,您需要明确地为您的SUM列设置别名,例如SUM(TEMP.SUMCARD) AS SUMCARD

英文:

The problem is that your query doesn't actually have columns SUMCARD, SUMERRORTXN and SUMERRORTXNCARD. Although there are DBMSes that alias SUM columns with the name of the column that is summed, Oracle is not one of them. IIRC, Oracle aliases it as, for example, &quot;SUM(SUMCARD)&quot; or maybe &quot;SUM(TEMP.SUMCARD)&quot;. However, that is an implementation detail you should not rely on in my opinion.

To get the name you want to use, you need to alias your SUM columns explicitly, e.g. SUM(TEMP.SUMCARD) AS SUMCARD.

huangapple
  • 本文由 发表于 2023年2月10日 15:39:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75408161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定