文章目录

  • 前言
  • 1.Javabean对应数据库类型
  • 2.工具类
  • 2.1封装BigDecimal比较的工具类
  • 2.2封装计算的工具类(使用浮点数的方法)
  • 3.常见报错以及处理
  • 1.除法不一定能整除
  • 2.**分母不能为0!!!!!!**
  • 4.整合spring boot查询添加账单小案例


前言

近期做到项目是有关金额这一块,虽然只是记录,而且对要求精度不是那么高。不够平时基本没用过,所以还是尝试使用了BigDecimal。当然其实可以用double类型不够,然后使用工具类进行相对精确的计算。下面会放上一些工具类。

关于Java详解的有相关的文章,我有一篇不错的已经转载下来地址可回看:

1.Javabean对应数据库类型

因为肯定涉及到数据库的操作,所以先看看java类型和字段属性对应管理
(以下是MySQL为例)

类型名称

显示长度

数据库类型

JAVA类型

JDBC类型索引(int)

VARCHAR

L+N

VARCHAR

java.lang.String

12

CHAR

N

CHAR

java.lang.String

1

BLOB

L+N

BLOB

java.lang.byte[]

-4

TEXT

65535

VARCHAR

java.lang.String

-1

INTEGER

4

INTEGER UNSIGNED

java.lang.Long

4

TINYINT

3

TINYINT UNSIGNED

java.lang.Integer

-6

SMALLINT

5

SMALLINT UNSIGNED

java.lang.Integer

5

MEDIUMINT

8

MEDIUMINT UNSIGNED

java.lang.Integer

4

BIT

1

BIT

java.lang.Boolean

-7

BIGINT

20

BIGINT UNSIGNED

java.math.BigInteger

-5

FLOAT

4+8

FLOAT

java.lang.Float

7

DOUBLE

22

DOUBLE

java.lang.Double

8

DECIMAL

11

DECIMAL

java.math.BigDecimal

3

BOOLEAN

1

同TINYINT

ID

11

PK (INTEGER UNSIGNED)

java.lang.Long

4

DATE

10

DATE

java.sql.Date

91

TIME

8

TIME

java.sql.Time

92

DATETIME

19

DATETIME

java.sql.Timestamp

93

TIMESTAMP

19

TIMESTAMP

java.sql.Timestamp

93

YEAR

4

YEAR

java.sql.Date

91

对于bolb,一般用于对图片的数据库存储,原理是把图片打成二进制,然后进行的一种存储方式,在java中对应byte[]数组。


对于boolen类型,在mysql数据库中,个人认为用int类型代替较好,对bit操作不是很方便,尤其是在具有web页面开发的项目中,表示0/1,对应java类型的Integer较好。


decimal列的声明语法是decimal(m,d)。


在mysql5.1中,参数的取值范围:
1、M是数字的最大数(精度)。其范围为1~65(在较旧的MySQL版本中,允许的范围是1~254)。
2、D是小数点右侧数字的数目(标度)。其范围是0~30,但不得超过M。
说明:float占4个字节,double占8个字节,decimail(M,D)占M+2个字节。
如DECIMAL(5, 2) 的最大值为9 9 9 9 . 9 9,因为有7 个字节可用。

像我们的单笔账单大多数情况下不超过亿可以使用DECIMAL(10,2)

可参考:

2.工具类

2.1封装BigDecimal比较的工具类

import java.math.BigDecimal;

public final class DecimalUtils {

    private final BigDecimal value;

    public DecimalUtils(BigDecimal value) {
        this.value = value;
    }

    public static DecimalUtils of(BigDecimal value) {
        return new DecimalUtils(value);
    }

    // 小于
    public boolean lt(BigDecimal val) {
        return value.compareTo(val) == -1;
    }

    // 等于
    public boolean eq(BigDecimal val) {
        return value.compareTo(val) == 0;
    }

    // 大于
    public boolean gt(BigDecimal val) {
        return value.compareTo(val) == 1;
    }

    // 大于等于
    public boolean ge(BigDecimal val) {
        return value.compareTo(val) > -1;
    }

    // 小于等于
    public boolean le(BigDecimal val) {
        return value.compareTo(val) < 1;
    }
}

调用示例:

BigDecimal a = new BigDecimal("0.02");
BigDecimal b = new BigDecimal("0.01");
boolean bool = Decimal.of(a).ge(b);

2.2封装计算的工具类(使用浮点数的方法)

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 精确的浮点数运算
 * 
 * @author ruoyi
 */
public class Arith
{

    /** 默认除法运算精度 */
    private static final int DEF_DIV_SCALE = 10;

    /** 这个类不能实例化 */
    private Arith()
    {
    }

    /**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
     * 小数点以后10位,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2)
    {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        if (b1.compareTo(BigDecimal.ZERO) == 0)
        {
            return BigDecimal.ZERO.doubleValue();
        }
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }
}

而BigDecimal直接调用Java提供的Api即可!!!

3.常见报错以及处理

1.除法不一定能整除

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result异常的解决方法

先说一下为什么会有这个异常,其实是因为计算中,有时候我们会使用除法,但是值得注意的是我们的除法并不是都可以整除。所以我们调用方法的是时候应该使用带有保留位数,以及有小数处理的方法,而不是直接两个数字相除!!!!!

mysql decimal最多小数_数据库


其中2是保留即为两位小数,而后面的则是四舍五入的处理方法。

2.分母不能为0!!!!!!