如何从数据库获取DECIMAL类型小数点前后的位数限制?
解决DECIMAL类型随机值生成问题
核心问题
你当前只通过ResultSetMetaData.getPrecision()获取了DECIMAL列的总位数,但DECIMAL类型需要**总精度(precision)和小数位数(scale)**两个参数才能生成符合格式的随机值。比如DECIMAL(4,2),总精度是6(4+2),但小数位数是2,你需要分别生成4位整数和2位小数的组合。
解决方案步骤
1. 补充收集小数位数(scale)
在收集列限制信息时,同时调用ResultSetMetaData.getScale(int column)获取DECIMAL列的小数位数:
List<Integer> columnPrecisions = new ArrayList<>(); List<Integer> columnScales = new ArrayList<>(); ResultSetMetaData metaData = resultSet.getMetaData(); for (int i = 1; i <= metaData.getColumnCount(); i++) { columnPrecisions.add(metaData.getPrecision(i)); columnScales.add(metaData.getScale(i)); // 同时收集你已有的columnTypes列表 }
2. 修改随机值生成逻辑
修改createRecords方法,新增小数位数参数,针对DECIMAL类型拆分整数和小数部分生成:
public List<List<String>> createRecords(List<String> columnTypes, List<Integer> columnPrecisions, List<Integer> columnScales) { List<String> record = new ArrayList<>(); ThreadLocalRandom random = ThreadLocalRandom.current(); // 复用随机实例,提升效率 for (int j = 0; j < columnTypes.size(); j++) { switch (columnTypes.get(j)) { case "DECIMAL": int precision = columnPrecisions.get(j); int scale = columnScales.get(j); int integerDigits = precision - scale; String decimalStr; if (integerDigits <= 0) { // 处理整数部分为0的情况,比如DECIMAL(2,2) int decimalPart = random.nextInt((int) Math.pow(10, scale)); decimalStr = String.format("0.%0" + scale + "d", decimalPart); } else { // 生成整数部分(1到10^integerDigits -1) long integerPart = random.nextLong(1, (long) Math.pow(10, integerDigits)); // 生成小数部分(补零到指定位数) int decimalPart = random.nextInt((int) Math.pow(10, scale)); decimalStr = String.format("%d.%0" + scale + "d", integerPart, decimalPart); } record.add(decimalStr); break; case "INTEGER": record.add(String.valueOf(random.nextInt())); break; case "CHAR": record.add("'" + common.randomString(columnPrecisions.get(j)) + "'"); break; default: log.error("未知数据类型:" + columnTypes.get(j)); } } return new ArrayList<>(Collections.singleton(record)); }
3. 优化辅助方法(可选)
替换原convertMaxValueForRandomizer方法,用更简洁的方式生成位数对应的最大值:
public long getMaxValueByDigits(int digitCount) { if (digitCount <= 0) return 1; return (long) Math.pow(10, digitCount); }
说明
- 用
ThreadLocalRandom替代Random,避免多线程环境下的性能问题。 - 通过
String.format确保小数部分始终是指定的位数(不足补零)。 - 处理了整数部分为0的边界情况,适配
DECIMAL(s,s)这类特殊定义。
内容的提问来源于stack exchange,提问作者GreenLi9ht
相关产品推荐
相关产品推荐

