一天前,在添加新的接口(interface)实现后,我在代码中发现了一些奇怪的行为。
我看到 mybatis 更新总是返回 -1,并且表未更新。
Log 告诉我一些有趣的行为:- 创建新的 SqlSession
- SqlSession [...] 未注册同步,因为同步未激活
- JDBC 连接 [...] 将不会由 Spring 管理
- ==> 准备:更新卡组 amount=isnull(?, amount), name=isnull(?, name),balanceTime=isnull(?,balanceTime) where number=?和 clientId=?.
- ==> 参数:0.00(BigDecimal)、测试卡(String)、2017-02-22 09:05:24.78(Timestamp)、0000000000000000(String)、111000(Long)
- 关闭非事务性 SqlSession [...]
将参数发送到服务器后没有任何反应。 这发生在我的 DAO 被重构之后:
public class DBaseCard{
private long id;
private String number;
private String name;
private BigDecimal amount; // was Double
.....
}
在生产中我使用 Sybase IQ。对于测试,我使用 H2 db,一切正常。
如果我将“金额”字段类型更改为 Double,一切正常。
如果我保留 BigDecimal 类型并将“amount=isnull(#{card.amount}, amount)”替换为“amount=#{card.amount}”或类似“amount=isnull(0.00, amount)”的内容,则一切正常,在日志中我看到:
- ==> 参数:0.0(BigDecimal), ....
- <==更新:1
请帮助我理解为什么会发生这种情况。
最佳答案
这可能与Sybase中的列类型有关,H2可能有更宽松的行为。
查看 Mybatis default type handlers 的文档:
使用 BigDecimal:
BigDecimalTypeHandler java.math.BigDecimal Any compatible NUMERIC or DECIMAL
双倍:
DoubleTypeHandler java.lang.Double, double Any compatible NUMERIC or DOUBLE
它可能来自isnull函数。您可以尝试用coalesce替换。
尽管在日志中,您会看到 0.00(BigDecimal)
, 0.00
只是 Java BigDecimal 的字符串表示形式,驱动程序实际绑定(bind)的值可能与 null 相同,例如 0
,有时0==null
而0!==null
,这可以解释为什么硬编码 0.00
按预期工作。
可以选择编写存储过程。
您也可以考虑使用Mybatis dynamic SQL (trim, where, set) 来构建 SET,这样您就不必再依赖 isnull 了:
UPDATE
<set>
<if test="amount!= null">amount=#{amount},</if>
<if test="name!= null">name=#{name},</if>
<if test="balanceTime!= null">balanceTime=#{balanceTime} </if>
</set>
WHERE number=#{number} AND clientId=#{clientId}
如果您不能保证 SET 中会有某些内容(至少有 1 个非空参数),则<set>
必须包含(在最后一行)中性的内容(没有实际更新),例如:id=id
.
关于java - mybatis 的一些奇怪问题以及 Sybase 的 BigDecimal 上的 isnull,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42410386/