Search code examples
javaspring-data-jpadoubleprecision

[Spring Data JPA]: @Column(scale) parameter has no effect


I have the following DAO that is supposed to model bank accounts.

@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()
}

(I am aware that for balances one ought to best use BigDecimal instead of Float or Double, and it's happening in the next iteration. This is not production - grade code by any means.)

My repository for this DAO simply extends JPARepository<AccountDao, String>:

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

The relevant controller and service class methods are relatively straightforward:

Controller POST endpoint:

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

Service method storeAccount():

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());
    }
  }

When I POST the following payload:

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

My database (MySQL Ver 8.0.33-0ubuntu0.20.04.2) persists the Double with all the decimal digits, ignoring the scale = 2 option that I have provided to the @Column annotation.

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

Why does this happen? What am I doing wrong here (besides not using BigDecimal; see above)?


Solution

  • Turns out that actually my problem is most likely exactly that I don't use a BigDecimal. Based on the comments in the accepted answer of this thread, the scale parameter of the @Column annotation will NOT work for Double fields, but it WILL work for BigDecimal fields.