Mybatis的批量插入Bigdecimal会丢失精度

简介: Mybatis的批量插入Bigdecimal会丢失精度

分析

MyBatis在批量插入BigDecimal类型的数据时,可能会出现精度丢失的问题。这主要是由于Java的BigDecimal类型和数据库的DECIMAL或NUMERIC类型之间的精度差异造成的。

Java的BigDecimal类型用于表示精确的浮点数,可以指定任意的精度(小数点后的位数)。而数据库中的DECIMAL或NUMERIC类型也有精度的概念,但是它们通常有一个固定的精度限制,比如DECIMAL(10, 2)表示总共有10位数,其中小数点后有2位。

当你尝试将一个高精度的BigDecimal值存储到数据库中的低精度的DECIMAL或NUMERIC字段时,就可能出现精度丢失的问题。

为了解决这个问题,可以考虑以下几点:

确保精度匹配:确保你的Java代码中的BigDecimal的精度与数据库字段的精度匹配。如果数据库字段的精度较低,那么在插入数据之前,你可以通过BigDecimal的setScale方法来设置合适的精度。

使用适当的数据库类型:如果可能的话,可以考虑使用数据库支持的高精度数值类型,如PostgreSQL的NUMERIC类型或MySQL的DECIMAL类型,它们可以支持更高的精度。

自定义类型处理器:你可以创建一个自定义的类型处理器(TypeHandler),在插入和查询时,对BigDecimal进行适当的精度处理。

下面是一个简单的例子,展示了如何在MyBatis中使用自定义的类型处理器来处理BigDecimal:

public class BigDecimalTypeHandler extends BaseTypeHandler<BigDecimal> {  
  
    @Override  
    public void setNonNullParameter(PreparedStatement ps, int i, BigDecimal parameter, JdbcType jdbcType) throws SQLException {  
        // 设置合适的精度,这里设置为2位小数  
        BigDecimal scaledValue = parameter.setScale(2, BigDecimal.ROUND_HALF_UP);  
        ps.setBigDecimal(i, scaledValue);  
    }  
  
    @Override  
    public BigDecimal getNullableResult(ResultSet rs, String columnName) throws SQLException {  
        BigDecimal value = rs.getBigDecimal(columnName);  
        return value;  
    }  
}

在你的MyBatis配置文件中,注册这个自定义类型处理器:

<typeHandlers>  
  <typeHandler handler="com.example.BigDecimalTypeHandler" javaType="java.math.BigDecimal" jdbcType="DECIMAL"/>  
</typeHandlers>

这样在处理BigDecimal类型的数据时,MyBatis就会使用你的自定义类型处理器,从而避免精度丢失的问题。

实战

下面这种批量插入的时候

<foreach collection="list" item="item" separator=",">
#{item.useWorkingHours,jdbcType=DECIMAL}
</foreach>

useWorkingHours是decimal类型,在插入多条数据,取值如 0.1,0.81时 数据0.81会都变成0.8,丢失精度

网上的解决方案:

 cast(#{item.weeklyInputPercentage,jdbcType=DECIMAL} as decimal(10,2))

对我没用效果

在代码里面去改

workingHoursManagement.setWeeklyInputPercentage(workingHoursManagement.getWeeklyInputPercentage().setScale(2, RoundingMode.HALF_UP));

解决了

总结

MyBatis批量插入BigDecimal的原理主要涉及到JDBC的批处理技术和Java的BigDecimal类型。

JDBC批处理技术:JDBC(Java Database Connectivity)是Java中用于连接和操作数据库的一种技术。在JDBC中,为了提高数据库插入、更新等操作的效率,提供了一种叫做批处理(Batch Processing)的技术。在批处理中,多个数据库操作被打包成一个批次,一次性发送给数据库服务器,减少了网络传输的次数,提高了效率。

Java BigDecimal类型:BigDecimal是Java的一个类,用于对超大的浮点数进行运算。BigDecimal可以准确地表示小数,包括那些接近但不等于1的小数,避免了浮点数运算的精度问题。

在MyBatis中,当你要插入大量BigDecimal类型的数据时,可以使用批处理技术来提高效率。你可以通过以下步骤来实现:

创建SqlSession:SqlSession是MyBatis中用于执行SQL的主要接口。你可以通过SqlSession的批量操作(executeBatch)来执行批处理。

构建SQL语句:使用MyBatis的XML映射文件或注解来构建SQL语句。在SQL语句中,使用Java的BigDecimal类型来表示要插入的数据。

执行批处理:通过SqlSession的批量操作(executeBatch)来执行SQL语句。在执行批处理时,多个SQL语句会被打包成一个批次,一次性发送给数据库服务器。

关闭SqlSession:在执行完批处理后,要关闭SqlSession以释放资源。

需要注意的是,虽然批处理技术可以提高效率,但是如果一次插入的数据量太大,可能会消耗过多的内存。因此,在执行批处理时,要注意控制批次的大小,以避免内存溢出。

目录
相关文章
|
4天前
|
SQL 存储 Kubernetes
Seata常见问题之mybatisplus的批量插入方法报SQL错误如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
58 0
|
4天前
|
SQL Java 数据库连接
Mybatis查询的时候BigDecimal类型的值查询失效的解决办法
Mybatis查询的时候BigDecimal类型的值查询失效的解决办法
|
4天前
|
存储 Java 数据库连接
MyBatis Plus中的批量插入:通过开启rewriteBatchedStatements=true
MyBatis Plus中的批量插入:通过开启rewriteBatchedStatements=true
174 0
|
4天前
|
Java 数据库连接 mybatis
mybatis 批量插入
mybatis 批量插入
27 0
|
10月前
|
SQL Java 数据库连接
MyBatis痛点验证,使用 foreach 批量插入慢?
MyBatis痛点验证,使用 foreach 批量插入慢?
189 0
|
10月前
|
SQL Java 数据库连接
如何使用Mybatis实现批量插入 ?
如何使用Mybatis实现批量插入 ?
51 0
|
11月前
|
小程序 Java 数据库连接
【实践】mybatis批量插入map
【实践】mybatis批量插入map
492 0
|
SQL 缓存 JavaScript
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 下
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 下
|
SQL Java 数据库连接
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 上
从120s到2.5s!看看人家的MyBatis批量插入数据优化,那叫一个优雅! 上
|
SQL 缓存 Oracle
MyBatis 批量插入别再乱用 foreach 了,5000 条数据花了 14 分钟。。。
MyBatis 批量插入别再乱用 foreach 了,5000 条数据花了 14 分钟。。。