Java mybatis有些奇怪,Sybase的BigDecimal上的isnull
前一天,在添加新的接口实现后,我在代码中发现了一些奇怪的行为 我看到mybatis更新始终返回-1,并且表未更新 Log告诉我一些有趣的行为: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
- 创建新的SqlSession
- SqlSession[…]未注册同步,因为同步未处于活动状态
- JDBC连接[…]将不由Spring管理
- ==>准备:更新卡集金额=isnull(?,金额),名称=isnull(?,名称),余额时间=isnull(?,余额时间),其中数字=?clientId=
- ==>参数:0.00(大十进制),测试卡(字符串),2017-02-22 09:05:24.78(时间戳),0000000000000000(字符串),111000(长)
- 正在关闭非事务性SqlSession[…]
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)
只是Java BigDecimal的字符串表示形式,驱动程序实际绑定的值可能与null相同,例如0.00
,有时0
,而0==null
0==null,这可以解释为什么硬编码的
可以按预期工作 编写存储过程是一个选项0.00
您还可以考虑使用(<强>修剪,在哪里,设置< /强>)来构建集合,这样您就不再需要依赖于ISNULL:
更新 金额=#{amount}, 名称=#{name}, balanceTime=#{balanceTime} 其中number={number}和clientId={clientId}
如果不能保证集合中会有某些内容(至少1个NOTNULL参数),
必须(在最后一行)包含一些中性的内容(无实际更新),例如:
它可能与Sybase中的列类型有关,H2可能具有更宽松的行为 检查以下文件: 使用BigDecimal: BigDecimalTypeHandler java.math.BigDecimal任何兼容的 数字或十进制 双倍: DoubleTypeHandler java.lang.Double,Double任何兼容的 数字或双精度 它可能来自isnull函数。你可以试着用coalesce替换 即使在日志中,您也会看到id=id
,0.00(BigDecimal)
只是Java BigDecimal的字符串表示形式,驱动程序实际绑定的值可能与null相同,例如0.00
,有时0
,而0==null
0==null,这可以解释为什么硬编码的
可以按预期工作 编写存储过程是一个选项0.00
您还可以考虑使用(<强>修剪,在哪里,设置< /强>)来构建集合,这样您就不再需要依赖于ISNULL:
更新 金额=#{amount}, 名称=#{name}, balanceTime=#{balanceTime} 其中number={number}和clientId={clientId}
如果您不能保证集合中会有某些内容(至少1个非空参数),
必须包含(在最后一行)中性内容(无实际更新),例如:
我发现了问题的主要原因。在查看了一段时间mybatis源代码之后,我了解到,在我的例子中,mybatis或SQL本身并没有任何内容。SQL请求工作于ui客户端,不会工作于代码。我创建了一个简单的测试:id=id
我尝试了“conn_string”的一些变体:“jdbc:jtds:sybase://...和“jdbc:sybase:Tds://…”。jConnect驱动程序在更新时返回1,而不是jTDS驱动程序返回0Connection 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();
看起来像是jTDS驱动程序中的错误?我找到了问题的主要原因。在查看了一段时间mybatis源代码之后,我了解到,在我的例子中,mybatis或SQL本身并没有任何内容。SQL请求工作于ui客户端,不会工作于代码。我创建了一个简单的测试:
我尝试了“conn_string”的一些变体:“jdbc:jtds:sybase://...和“jdbc:sybase:Tds://…”。jConnect驱动程序在更新时返回1,而不是jTDS驱动程序返回0Connection 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();
看起来像是jTDS驱动程序中的错误?谢谢您的帮助!你对我的问题考虑得很好。所以我为自己的问题创造了答案。谢谢你们的帮助!你对我的问题考虑得很好。所以我为自己的问题创造了答案。