文章目录
- 前言
- 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异常的解决方法
先说一下为什么会有这个异常,其实是因为计算中,有时候我们会使用除法,但是值得注意的是我们的除法并不是都可以整除。所以我们调用方法的是时候应该使用带有保留位数,以及有小数处理的方法,而不是直接两个数字相除!!!!!
其中2是保留即为两位小数,而后面的则是四舍五入的处理方法。
2.分母不能为0!!!!!!