Java mybatis有些奇怪,Sybase的BigDecimal上的isnull

Java mybatis有些奇怪,Sybase的BigDecimal上的isnull,java,mybatis,bigdecimal,isnull,Java,Mybatis,Bigdecimal,Isnull,前一天,在添加新的接口实现后,我在代码中发现了一些奇怪的行为 我看到mybatis更新始终返回-1,并且表未更新 Log告诉我一些有趣的行为: 创建新的SqlSession SqlSession[…]未注册同步,因为同步未处于活动状态 JDBC连接[…]将不由Spring管理 ==>准备:更新卡集金额=isnull(?,金额),名称=isnull(?,名称),余额时间=isnull(?,余额时间),其中数字=?clientId= ==>参数:0.00(大十进制),测试卡(字符串),2017-0

前一天,在添加新的接口实现后,我在代码中发现了一些奇怪的行为 我看到mybatis更新始终返回-1,并且表未更新

Log告诉我一些有趣的行为:

  • 创建新的SqlSession
  • SqlSession[…]未注册同步,因为同步未处于活动状态
  • JDBC连接[…]将不由Spring管理
  • ==>准备:更新卡集金额=isnull(?,金额),名称=isnull(?,名称),余额时间=isnull(?,余额时间),其中数字=?clientId=
  • ==>参数:0.00(大十进制),测试卡(字符串),2017-02-22 09:05:24.78(时间戳),0000000000000000(字符串),111000(长)
  • 正在关闭非事务性SqlSession[…]
将参数发送到服务器后,什么也没有发生。 这是在重构DAO之后发生的:

public class DBaseCard{
    private long id;
    private String number;
    private String name;
    private BigDecimal amount; // was Double
    .....
}
在生产中,我使用Sybase IQ。对于测试,我使用h2db,对于它,所有的工作都很好

如果我将“金额”字段类型更改为Double,则一切正常。

如果我保留BigDecimal类型并将“amount=isnull(#{card.amount},amount)”替换为“amount=#{card.amount}”或类似于“amount=isnull(0.00,amount)”的内容,则一切正常,在日志中我看到:

  • ==>参数:0.0(BigDecimal)

  • 这可能和Sybase中的列类型有关,H2可能具有更宽松的行为

    检查以下文件:

    使用BigDecimal:

    BigDecimalTypeHandler java.math.BigDecimal任何兼容的 数字或十进制

    双倍:

    DoubleTypeHandler java.lang.Double,Double任何兼容的 数字或双精度

    它可能来自isnull函数。你可以试着用coalesce替换

    即使在日志中,您也会看到
    0.00(BigDecimal)
    0.00
    只是Java BigDecimal的字符串表示形式,驱动程序实际绑定的值可能与null相同,例如
    0
    ,有时
    0==null
    ,而
    0==null,这可以解释为什么硬编码的
    0.00
    可以按预期工作

    编写存储过程是一个选项

    您还可以考虑使用(<强>修剪,在哪里,设置< /强>)来构建集合,这样您就不再需要依赖于ISNULL:

    更新
    金额=#{amount},
    名称=#{name},
    balanceTime=#{balanceTime}
    其中number={number}和clientId={clientId}
    

    如果不能保证集合中会有某些内容(至少1个NOTNULL参数),
    必须(在最后一行)包含一些中性的内容(无实际更新),例如:
    id=id

    它可能与Sybase中的列类型有关,H2可能具有更宽松的行为

    检查以下文件:

    使用BigDecimal:

    BigDecimalTypeHandler java.math.BigDecimal任何兼容的 数字或十进制

    双倍:

    DoubleTypeHandler java.lang.Double,Double任何兼容的 数字或双精度

    它可能来自isnull函数。你可以试着用coalesce替换

    即使在日志中,您也会看到
    0.00(BigDecimal)
    0.00
    只是Java BigDecimal的字符串表示形式,驱动程序实际绑定的值可能与null相同,例如
    0
    ,有时
    0==null
    ,而
    0==null,这可以解释为什么硬编码的
    0.00
    可以按预期工作

    编写存储过程是一个选项

    您还可以考虑使用(<强>修剪,在哪里,设置< /强>)来构建集合,这样您就不再需要依赖于ISNULL:

    更新
    金额=#{amount},
    名称=#{name},
    balanceTime=#{balanceTime}
    其中number={number}和clientId={clientId}
    

    如果您不能保证集合中会有某些内容(至少1个非空参数),
    必须包含(在最后一行)中性内容(无实际更新),例如:
    id=id

    我发现了问题的主要原因。在查看了一段时间mybatis源代码之后,我了解到,在我的例子中,mybatis或SQL本身并没有任何内容。SQL请求工作于ui客户端,不会工作于代码。我创建了一个简单的测试:

        Connection conn = DriverManager.getConnection("conn_string", "login", "pass");
    
        PreparedStatement ps = conn.prepareStatement("update Card set amount=isnull(?, amount), name=isnull(?, name), balanceTime=isnull(?, balanceTime) where number=? and clientId=?");
    
        //ps.setDouble(1, 12.23);
        ps.setBigDecimal(1, new BigDecimal("155.0"));
        ps.setString(2, "Test test");
        ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
        ps.setString(4, "00000000000000");
        ps.setLong(5, 111010111L);
    
        LOG.info("execute update result: {}", ps.executeUpdate());
    
        conn.close();
    
    我尝试了“conn_string”的一些变体:“jdbc:jtds:sybase://...和“jdbc:sybase:Tds://…”。jConnect驱动程序在更新时返回1,而不是jTDS驱动程序返回0


    看起来像是jTDS驱动程序中的错误?

    我找到了问题的主要原因。在查看了一段时间mybatis源代码之后,我了解到,在我的例子中,mybatis或SQL本身并没有任何内容。SQL请求工作于ui客户端,不会工作于代码。我创建了一个简单的测试:

        Connection conn = DriverManager.getConnection("conn_string", "login", "pass");
    
        PreparedStatement ps = conn.prepareStatement("update Card set amount=isnull(?, amount), name=isnull(?, name), balanceTime=isnull(?, balanceTime) where number=? and clientId=?");
    
        //ps.setDouble(1, 12.23);
        ps.setBigDecimal(1, new BigDecimal("155.0"));
        ps.setString(2, "Test test");
        ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
        ps.setString(4, "00000000000000");
        ps.setLong(5, 111010111L);
    
        LOG.info("execute update result: {}", ps.executeUpdate());
    
        conn.close();
    
    我尝试了“conn_string”的一些变体:“jdbc:jtds:sybase://...和“jdbc:sybase:Tds://…”。jConnect驱动程序在更新时返回1,而不是jTDS驱动程序返回0


    看起来像是jTDS驱动程序中的错误?

    谢谢您的帮助!你对我的问题考虑得很好。所以我为自己的问题创造了答案。谢谢你们的帮助!你对我的问题考虑得很好。所以我为自己的问题创造了答案。