0

My Spring Boot application uses Spring Data JPA / Hibernate with a MariaDB 10.4.16. The database belongs to a legacy system. For testing, I'd like to generate the schema from the entities.

src/test/resources/application.yml

spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: create-drop
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
    properties:
      hibernate:
        dialect:
          storage-engine: innodb
        format_sql: true
        order_inserts: true
        order_updates: true
        use_sql_comments: true

Persisting to the database fails with:

Field 'id' doesn't have a default value

The entity class:

@Entity
@Table(name = "my_entity")
public class MyEntity implements Serializable {

    private static final long serialVersionUID = 109811363263266332L;

    @Id
    @GeneratedValue
    @Column(name = "id")
    private long id;

    @Column(name = "subject")
    private String subject;
}

I tried changing the @GeneratedValue strategies to AUTO and IDENTITY but none has an effect.


Update 1

After doing some more debugging, I found out that this behavior is caused by a custom generator (legacy codde) for the id. I didn't see this at glance. This custom generator is applied to other entities (haven't found out why yet) but not for MyEntity.

@Id
@Access(PROPERTY)
@GenericGenerator(name = "IdOrGenerated", strategy = "MyCustomGenerator")
@GeneratedValue(strategy = IDENTITY, generator = "IdOrGenerated")
private long id;
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) {
    Long id = (Long) session.getEntityPersister(null, object)
            .getClassMetadata().getIdentifier(object, session);
    return id != null && id != 0L  ? id : defaultGenerator.generate(session, object);
}

This returns POST_INSERT_INDICATOR:
https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/id/IdentifierGeneratorHelper.html#POST_INSERT_INDICATOR

When replacing the custom generator, then it works. It also works if I explicitly call myEntity.setId(123L). Of course, that's not an option but it maybe provides some hint.

Robert Strauch
  • 12,055
  • 24
  • 120
  • 192

1 Answers1

0

I found valuable information in this answer. Changing the custom generator to the following resolves the problem in my case:

public class UseExistingOrGenerateIdGenerator extends IdentityGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) {
        Long id = (Long) session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
        return id != null && id != 0L ? id : super.generate(session, object);
    }
}
Robert Strauch
  • 12,055
  • 24
  • 120
  • 192