gawkingdotnet520 2025-04-03 10:58 采纳率: 0%
浏览 8

JAVA处理postgresql 的numeric类型时随机触发异常应如何处理

JAVA 在处理 numeric 类型(如期初金额)时,底层接收数据库返回的值 有时会随机 变成小于8个字节的情况,导致Java执行 numeric转换时,小于8个字节就报异常:

img

数据库结构:

img

mybatis 语句如下:

<select id="getInitMoney" resultType="java.lang.String">
    SELECT /*+ set(query_dop 16) */
        COALESCE(SUM(ca.js_money),0)::numeric(20,6) as js_money  FROM v_check_account ca
    WHERE
        ca.corp_id = #{query.corpId,jdbcType=BIGINT}
        AND ca.trader_id = #{query.traderId,jdbcType=BIGINT}
        AND ca.acc_date &lt; #{query.startDate,jdbcType=INTEGER}
</select>

接口:
String getInitMoney(@Param("query") CheckAccountQuery query);

处理方式:
String initStr = reportDao.getInitMoney(query);--这行报异常
BigDecimal init = BigDecimal.valueOf(Double.parseDouble(initStr));

这个要怎么处理才好哇。它就是随机的,有时异常,有时又正常。
我查deepseek,说是 可能3种情况:

img

1、高斯数据库驱动版本过低(目前postgresql的依赖包是42.7.5,我搜了下已经是最新的了);

img

2、联系数据库管理员,确认是否配置numeric返回8个字节以上(等待答复);
3、这个试过不行,即使将自己处理到8位以上,还会其他可能异常等着:

img

  • 写回答

4条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2025-04-03 10:58
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 关键点分析
      - 主要问题是Java处理PostgreSQL的numeric类型时,数据库返回的值有时会随机小于8个字节,导致Java进行numeric转换时抛出异常。
      - 涉及到Java与PostgreSQL的交互,特别是数据类型的转换和处理。
    2. 解决方案
      - 方案一:在Java中进行数据长度检查和转换
      • 在Java代码中,当从数据库获取到numeric类型的值后,先检查其字节长度。
      • 如果长度小于8个字节,可以尝试进行特殊处理,比如在前面补零以达到8个字节再进行转换。
      • 示例代码如下:
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class NumericHandling {
        public static void main(String[] args) {
            String url = "jdbc:postgresql://your_host:your_port/your_database";
            String user = "your_user";
            String password = "your_password";
    
            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                String sql = "SELECT initial_amount FROM your_table";
                try (PreparedStatement pstmt = conn.prepareStatement(sql);
                     ResultSet rs = pstmt.executeQuery()) {
                    while (rs.next()) {
                        byte[] numericBytes = rs.getBytes("initial_amount");
                        if (numericBytes.length < 8) {
                            byte[] paddedBytes = new byte[8];
                            System.arraycopy(numericBytes, 0, paddedBytes, 8 - numericBytes.length, numericBytes.length);
                            // 这里假设你有一个将字节数组转换为numeric类型的方法
                            Object numericValue = convertBytesToNumeric(paddedBytes);
                        } else {
                            // 直接转换
                            Object numericValue = convertBytesToNumeric(numericBytes);
                        }
                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        private static Object convertBytesToNumeric(byte[] bytes) {
            // 这里需要根据实际的numeric类型转换逻辑实现
            // 例如,如果使用BigDecimal
            return new BigDecimal(new BigInteger(1, bytes));
        }
    }
    
    • 方案二:在数据库层面进行处理
      • 在PostgreSQL中,可以使用to_char函数将numeric类型转换为固定长度的字符串类型,确保返回的数据长度是一致的。
      • 然后在Java中直接将字符串类型转换为所需的Java类型。
      • 示例代码如下:
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.math.BigDecimal;
    
    public class NumericHandling {
        public static void main(String[] args) {
            String url = "jdbc:postgresql://your_host:your_port/your_database";
            String user = "your_user";
            String password = "your_password";
    
            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                String sql = "SELECT to_char(initial_amount, 'FM99999999') FROM your_table";
                try (PreparedStatement pstmt = conn.prepareStatement(sql);
                     ResultSet rs = pstmt.executeQuery()) {
                    while (rs.next()) {
                        String numericStr = rs.getString(1);
                        BigDecimal numericValue = new BigDecimal(numericStr);
                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    1. 方案优缺点
      - 方案一
      • 优点:灵活性高,可以在Java代码中根据具体业务需求进行定制化处理,不需要修改数据库查询语句。
      • 缺点:增加了Java代码的复杂性,特别是在处理字节数组转换和补零逻辑时。
      • 方案二
      • 优点:在数据库层面统一处理数据格式,减少了Java代码的处理逻辑,代码相对简洁。
      • 缺点:依赖数据库的特定函数,可能会影响数据库查询性能,并且如果数据库类型或版本变化,可能需要调整函数使用。
    2. 总结
      - 对于Java处理PostgreSQL的numeric类型时随机触发异常的问题,可以通过在Java中进行数据长度检查和转换,或者在数据库层面使用函数统一数据格式来解决。两种方案各有优缺点,需要根据具体项目情况选择合适的方法。如果对性能要求较高且数据库版本稳定,方案二可能更合适;如果需要更灵活的处理逻辑,方案一更为适合。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    评论

报告相同问题?

问题事件

  • 修改了问题 4月3日
  • 创建了问题 4月3日