postgresqljdbc

Rounding when setting scaled DECIMAL


If I set, say, 10.244 to a column of type DECIMAL(20,2), the actual saved value would be 10.24. If I set 10.245, 10.25 will be saved.

It makes sense. However, I'm curious:

  1. Which layer does it? A JDBC driver or a DB itself?
  2. Can I change how that layer rounds the decimals? For example, make it discard the redundant digits completely.

It appears it's not JDBC, at least judging from Hibernate logs. Note 11.264. 11.26 was actually saved.

Hibernate: 
    update
        account 
    set
        balance=?,
        initial_balance=?,
        user_id=? 
    where
        id=?
2025-05-30T14:37:17.472+03:00 TRACE 11240 --- [pool-2-thread-1] org.hibernate.orm.jdbc.bind              : binding parameter (1:NUMERIC) <- [11.264]
2025-05-30T14:37:17.473+03:00 TRACE 11240 --- [pool-2-thread-1] org.hibernate.orm.jdbc.bind              : binding parameter (2:NUMERIC) <- [10.24]
2025-05-30T14:37:17.474+03:00 TRACE 11240 --- [pool-2-thread-1] org.hibernate.orm.jdbc.bind              : binding parameter (3:BIGINT) <- [15]
2025-05-30T14:37:17.475+03:00 TRACE 11240 --- [pool-2-thread-1] org.hibernate.orm.jdbc.bind              : binding parameter (4:BIGINT) <- [1]

The value is represented as java.math.BigDecimal on the backend. I realize I can manually call bigDecimal.setScale(2, java.math.RoundingMode.DOWN) before trying to persist. It is not what I am asking.


Solution

    1. The db always does this regardless of what happens before. I don't think you can easily configure Hibernate and/or JDBC to do that on the fly, in some custom way. I guess the consensus is there's no reason to, since the db is handling it already, and that quietly overriding well-established behaviour would violate the principle of least surprise. Your discarded idea to do that explicitly before persisting might not be that bad after all.
    2. Default rounding behaviour isn't configurable in PostgreSQL, at least not without tinkering with the source and recompiling. In a standard build, in pure SQL context you could set up a virtual column in a view that applies your desired custom rounding expression to a value stored with larger scale, or a generated column that does the same and persists it, or swap out the typemod for a trigger that swoops in and re-writes your values whenever necessary. Technically, you could also build a whole new numeric type of your own and make it do that internally but please don't.