mybatis批量插入BigDecimal精度丢失了(非批量没有问题)

发布于 2021-12-02 18:28:23 字数 2838 浏览 921 评论 19

数据库为MSSQL2014

建表语句:

create table tb_test_user (id int not null identity, name nvarchar(50), balance decimal(19,5), interest decimal(19,5))

mapper.xml内容:

<mapper namespace="com.pp.jdbc.mapper.UserMapper">

	<insert id="batchInsert">
		INSERT INTO tb_test_user (name,balance,interest) VALUES
        <foreach collection="list" item="user" index="index" separator=",">
            (#{user.name},#{user.balance},#{user.interest})
        </foreach>
	</insert>
	
	<insert id="insert">
		INSERT INTO tb_test_user
        (name,balance,interest)
        VALUES
        (#{name},#{balance},#{interest})
	</insert>
	
</mapper>
public interface UserMapper {

	int insert(User user);
	
	int batchInsert(List<User> users);
}
import java.io.Serializable;
import java.math.BigDecimal;

import lombok.Data;

@Data
public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;

	private Integer id;
	private String name;
	private BigDecimal balance;
	private BigDecimal interest;
	
	public User() {}
	
	public User(String name, double balance, double interest) {
		this.name = name;
		this.balance = BigDecimal.valueOf(balance);
		this.interest = BigDecimal.valueOf(interest);
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", balance=" + balance + ", interest=" + interest + "]";
	}
}

调用

 

如果是调用批量的插入

public void save(UserMapper mapper) {
		List<User> users = new ArrayList<>();
    	users.add(new User("aa", 12d, 22d));
    	users.add(new User("bb", 12.1122d, 22.22333d));
    	users.add(new User("cc", 12.0d, 22.5d));
    	users.add(new User("dd", 12.5d, 22.2144d));
    	users.add(new User("ee", 12.7d, 22d));
    	users.add(new User("ff", 12.9874555d, 22.12341d));
    	mapper.batchInsert(users);
}

精度丢失了

 

但是,如果调用的是单个插入的方法,则没有问题

public void save(UserMapper mapper) {
		List<User> users = new ArrayList<>();
    	users.add(new User("aa", 12d, 22d));
    	users.add(new User("bb", 12.1122d, 22.22333d));
    	users.add(new User("cc", 12.0d, 22.5d));
    	users.add(new User("dd", 12.5d, 22.2144d));
    	users.add(new User("ee", 12.7d, 22d));
    	users.add(new User("ff", 12.9874555d, 22.12341d));
    	for(User user : users) {
    		mapper.insert(user);
    	}
}

 

请问,相同的代码,数据精度一样,为啥批量插入会有问题

 

 

 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

做个少女永远怀春 2021-12-08 20:49:09

为啥?$有SQL注入问题。另外,单条插入为啥没有问题

妖妓 2021-12-08 20:49:09

我这边遇到和你相同的问题,你是怎么解决的?

陌上芳菲 2021-12-08 20:49:08

不要用#用$

羁拥 2021-12-08 20:49:06

使用你上面的代码,插入到mysql,没有任何问题。

另外我的getter和setter都是写好的,没用lombok.

葬花如无物 2021-12-08 20:49:06

难道是MSSQL的问题?

彼岸花ソ最美的依靠 2021-12-08 20:49:05

看了大家的回复,大部分说是User构造函数有问题

this.balance = BigDecimal.valueOf(balance);
this.interest = BigDecimal.valueOf(interest);

说,这里是double转换成BigDecimal出了问题,实际上这里是没有问题的。BigDecimal.valueOf的源码为:

源码里面先把double转换成字符串,调用的是

Double.toString(val)

这句代码,是可以正常的把double转换成字符串,没有损失的。这里是没有问题的

 

综上所述,把double转换成BigDecimal的方法是没有问题的

别低头,皇冠会掉 2021-12-08 20:49:02

既然是bigdecimal 为什么用double创建,不是mybatis的问题是你自己弄错了

秋意浓 2021-12-08 20:49:02

double是因为不够精确,所以有时候会丢失数据精度,用bigdecimal重写下user构造函数就可以了

离去的眼神 2021-12-08 20:49:02

既然是bigdecimal 为什么用double创建??你的思路就有点问题  直接用string是最好的

 

把回忆走一遍 2021-12-08 20:49:00

试过了,不行。我真正的问题是,为啥单个没有问题,批量有问题

明媚如初 2021-12-08 20:49:00

直接字符串呗

德意的啸 2021-12-08 20:48:57

回复
你可以看mybatis org.apache.ibatis.builder.xml.XMLStatementBuilder 类parseStatementNode方法 SqlSource sqlSource 这行代码加个加个断点,看解析出来的参数类型

累赘 2021-12-08 20:48:56

回复
跟批量非批量没有关系。这种用法是不规范的,因此不能保证是否会出现问题。而你在实际测试中非批量恰好没有出问题。你可以换成String试试。

伪装你 2021-12-08 20:48:56

指定参数类型试试 #{user.balance,jdbcType=DECIMAL,javaType=java.math.BigDecimal  }

小情绪 2021-12-08 20:43:42

回复
规范的用法是?

秋意浓 2021-12-07 23:29:50

回复
你用double转String的时候就会出现精度问题,因此不要使用double。

眼眸 2021-12-06 14:01:12

看我下面的回复,使用BigDecimal.valueOf(balance);,把double转换成BigDecimal是没有问题的

疑心病 2021-12-05 19:15:08

回复
没啥可说的,打印出来看看就知道了

酒几许 2021-12-05 02:20:41

User构造器已经丢失精度了。BigDecimal要使用String初始化。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文