You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA中@Column的scale参数无效问题求助

问题:@Column的scale参数对Double类型字段无效的原因

实体类定义

@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ACCOUNT")
public class AccountDao {

  @Id
  @Column(name = "id", nullable = false)
  private String id;

  @Column(name = "balance", scale = 2)
  private Double balance;

  @Column(name = "currency")
  @Enumerated(EnumType.STRING)
  private Currency currency;

  @Column(name = "created_at")
  private Date createdAt;

  // equals(), hashcode()
}

注:已知余额最优类型为BigDecimal而非Double,后续会迭代修正,此代码非生产级

仓库接口

public interface AccountRepository extends JpaRepository<AccountDao, String> {}

控制器POST端点

@PostMapping("/newaccount")
public ResponseEntity<EntityModel<AccountDto>> postNewAccount(@RequestBody AccountDto accountDto) {
    accountService.storeAccount(accountDto);
    return ResponseEntity.ok(accountModelAssembler.toModel(accountDto));
}

服务层存储方法

public void storeAccount(AccountDto accountDto) throws AccountAlreadyExistsException{
    Optional<AccountDao> accountDao = accountRepository.findById(accountDto.getId());
    if (accountDao.isEmpty()) {
      accountRepository.save(
          new AccountDao(
              accountDto.getId(), accountDto.getBalance(), accountDto.getCurrency(), new Date()));
    } else {
      throw new AccountAlreadyExistsException(accountDto.getId());
    }
}

测试请求体

{
    "id" : "acc2",
    "balance" : 1022.3678234,
    "currency" : "USD"
}

数据库查询结果(MySQL 8.0.33)

mysql> select * from account where id = 'acc2';
+------+--------------+----------------------------+----------+
| id   | balance      | created_at                 | currency |
+------+--------------+----------------------------+----------+
| acc2 | 1022.3678234 | 2023-06-30 23:48:10.230000 | USD      |
+------+--------------+----------------------------+----------+

当前遇到的问题:数据库保留了Double类型的所有小数位,完全忽略了@Column(scale=2)的配置,除了未使用BigDecimal之外,导致scale参数无效的原因是什么?哪里操作有误?


答案
  • JPA规范中scale参数仅针对精确数值类型:scale和precision参数是为BigDecimal、BigInteger这类精确数值类型设计的,对于Double、Float这类浮点类型,JPA本身不支持用这两个参数约束小数位数。主流JPA实现(如Hibernate)会直接忽略浮点类型字段上的scale配置,因为浮点类型的设计目的是存储近似值,没有固定小数位的概念。

  • 数据库字段类型不匹配:如果MySQL中balance字段的类型是DOUBLE,而非DECIMAL(precision, scale),那么即使JPA配置了scale=2,数据库也不会对DOUBLE类型的数值做小数位截断或四舍五入。DOUBLE类型本身不支持指定固定小数位数,scale参数只有在数据库字段为DECIMAL/NUMERIC类型时才会生效。

  • 代码未主动处理小数位:当前代码直接将DTO中的Double值存入数据库,没有在服务层或DTO转换阶段做四舍五入到两位小数的处理。由于scale配置对Double无效,JPA不会自动处理小数位,数值会原封不动存储。

如果暂时不想切换到BigDecimal,可在代码中手动处理小数位,比如用Math.round(accountDto.getBalance() * 100) / 100.0保留两位小数后再存入数据库。


内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:53:16