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)?
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.