Search code examples
javahibernateh2

How to configure Hibernate6 default for Timestamp with a nanosecond precision?


I want Hibernate to save LocalDateTime properties in an H2 Database with a precision that contains nano seconds (Timestamp(9)) by default. "By default" means attaching @Column(columnDefinition = "TIMESTAMP(9)") to each LocalDateTime property cannot be the solution.

In Hibernate5, the solution was to create a custom dialect and call registerColumnType(Types.TIMESTAMP, "timestamp(9)") in its constructor.

However, I haven't found a solution for Hibernate6. I attempted to create a custom dialect and override resolveSqlTypeLength.

public class CustomH2Dialect extends H2Dialect {


    /* The Hibernate 5 Solution was to call registerColumnType(Types.TIMESTAMP, "timestamp(9)"); in the ctor.*/ 
    @Override
    public int resolveSqlTypeLength(String columnTypeName, int jdbcTypeCode, int precision, int scale,
            int displaySize) {
        if (jdbcTypeCode == Types.TIMESTAMP) {
            return 9;
        }        
        
        return super.resolveSqlTypeLength(columnTypeName, jdbcTypeCode, precision, scale, displaySize);
    }
}

But it seams that the method is not invoked.

Does anbody has an idea: how to configure TIMESTAMP(9) for all Timestamps (LocalDateTime...) in a default way? A git repo for tests can be found: https://gitlab.com/RalphEng/experiment-hibernate6-h2-datetime


Background: The use case are Spring Tests. I start Spring and a memmory H2 for the test. And I have a lot of tests that contains tests like:

MyEntity myEntity = new MyEntity ();
myEntity.timestamp = LocalDateTime.now();
myEntity.xzy = ....

entityManager.persist(myEntity);
entityManager.flush();
entityManager.clear();

MyEntity reloaded = entityManager.find(MyEntity .class, myEntity.getId());
assertThat(reloaded.timestamp).isEqualsTo(myEntity.timestamp)
//otherFieldsTo

To be honest the tests are in most cases not as simple as that and checking that the timestamp is exactly that same is not realy intended or needed. But I am not able to fix it. So increasing the precision is just a work arround for the tests.

And because it is only a "problem" in the tests, I can not add @Column(columnDefinition = "TIMESTAMP(9)") because this would also change the production behavior.


Solution

  • A Hibernate6 solution is to use a custom dialect and override the method getDefaultTimestampPrecision method to return 9:

    public class CustomH2Dialect extends H2Dialect {    
    
        @Override
        public int getDefaultTimestampPrecision() {
            return 9;
        }
    }