Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot 3/Hibernate 6 - How to annotate a simple field that has a DB managed DEFAULT value?

I have a Java @Entity class.

It has an @Id field, but that's not where the issue is so this is not about managing or creating Ids.

We have a number of other fields in the entity, some of which have DB managed default values, created with a sql query containing something like;

 blah blah VARCHAR(20) NOT NULL DEFAULT 'Blue';

We are using a Postgres database, flyway for DB migrations and zonky as the embeddable DB for component tests. So we are not using the Jpa to create our databases, just flyway.

Using 'spring-boot-starter-data-jpa', version: '2.7.6' we found the following to work fine with the DB defaults populated on insert as expected and also to be updateable/overwritten with new values on update;

@Generated(GenerationTime.INSERT)
@Column(name = "colour", nullable = false)
private String colour;

However, as we are now upgrading to SpringBoot 3/Hibernate 6 we have found that the GenerationTime is deprecated and we are struggling to find an annotation that will work. We have tried the new EventType.INSERT as shown below;

Example spring boot 3.1

@Generated(event = EventType.INSERT)
private String colour;

This new EventType enables the default to be generated when the field is null, but when we try to update the new field value is ignored and the default is maintained. In the same save(), other fields are updated ok. i.e. we call repository.save() with an entity where colour = red, but on retrieval and on DB inspection, the colour is still as default 'Blue', whereas other non-default enabled fields are updated correctly!

Any ideas how we should fix this? (Other than switching to Entity default definition, which we have been directed not to do!)

#data is set up in Flyway scripts as follows;

CREATE TABLE IF NOT EXISTS simple_account
(
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    last_name VARCHAR(255),
    home_office VARCHAR(255) NOT NULL DEFAULT 'Plymouth'
);

insert into simple_account (email, password, first_name, last_name, home_office)
VALUES ('[email protected]', 'password', 'user2', 'foo', 'Swansea');
    @Test
    public void testFindAndUpdateAccountPreviouslySaved() {
        String email = "[email protected]";
        SimpleAccount recovered = simpleAccountRepo.findByEmail(email);

        // check that we have the SimpleAccount that we are expecting
        assertEquals(email, recovered.getEmail());
        assertEquals("Swansea", recovered.getHomeOffice());

        // Set first_name (regular field) and home_office a not null default field 
        recovered.setFirstName("Bob");
        recovered.setHomeOffice("Blackpool");
        simpleAccountRepo.save(recovered);
        simpleAccountRepo.flush();

        SimpleAccount recovered2 = simpleAccountRepo.findByEmail(email);
        //Worked fine
        assertEquals("Bob", recovered2.getFirstName());

        //Failed to update
        assertEquals("Blackpool", recovered2.getHomeOffice());
    }
like image 624
jonny.l Avatar asked Aug 31 '25 01:08

jonny.l


1 Answers

After much reading on google and some trial and error, I have finally found something that works for all my test cases;

@GeneratedValue(strategy = GenerationType.AUTO)
private String colour;
  1. I can insert a new record with no value and the default is set.
  2. I can insert a new record with a different value and it is set instead of the default.
  3. I can retrieve an existing record with a default value and update that value!
like image 60
jonny.l Avatar answered Sep 02 '25 15:09

jonny.l