为什么hibernate忽略notnull约束?

hivapdat  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(397)

我遇到过有趣的冬眠行为。有人能解释一下为什么会这样吗?
技术栈:Java11/SpringBoot[2.3.2.release]/SpringData[2.3.2.release]/hibernate[5.4.18.final]。
我有一个liquibase创建的表:

<changeSet id="create-persons-table" author="author">
    <createSequence sequenceName="persons_seq"/>
    <createTable tableName="persons">
        <column name="id" type="bigint" defaultValueSequenceNext="persons_seq"/>
        <column name="name" type="varchar(255)"/>
        <column name="lastname" type="varchar(255)"/>
        <column name="es_identification" type="varchar(500)">
            <constraints nullable="false"/>
        </column>
        <column name="person_type" type="varchar(255)"/>
    </createTable>
</changeSet>

我有三个实体。基本实体、共同实体和国家特定实体:

@Getter
@Setter
@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = SEQUENCE, generator = "seq_gen")
    private Long id;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "person_type")
@SequenceGenerator(name = "seq_gen", sequenceName = "persons_seq", allocationSize = 1)
@Table(name = "persons")
public class Person extends BaseEntity {
    private String name;
    private String lastname;
}
@Entity
@NoArgsConstructor
@DiscriminatorValue("ES")
@Getter
@Setter
public class EsPerson extends Person {
    @Column(name = "es_identification", nullable = false)
    private String esIdentification;
}

我有相应的存储库:

@NoRepositoryBean
interface BaseRepository<T extends BaseEntity> extends JpaRepository<T, Long> {
    Optional<T> findById(Long id);

    default T requireById(Long id) {
        checkNotNull(id, "id cannot be null");
        return findById(id).orElseThrow(EntityNotFoundException::new);
    }
}
public interface PersonRepository extends BaseRepository<Person> {
}
public interface EsPersonRepository extends BaseRepository<EsPerson> {
}

所以魔法(对我来说)从我试图拯救埃斯珀森实体开始。

var person = new EsPerson();
person.setName("name");
person.setLastname("lastname");
person.setEsIdentification("es-identification");

esPersonRepository.save(esPerson);

在调试模式下,我看到所有属性都不是空的。但当我存钱的时候 org.postgresql.util.PSQLException: ERROR: null value in column 'es_identification' violates not-null constraint .
我打开了sql日志,看到hibernate插入了“name”、“lastname”和null。之后我关闭了“es\u identification”列的notnull约束,我看到hibernate首先插入“name”、“lastname”、null,然后更新“es\u identification”并设置相应的值。
所以这对我来说真的很奇怪。为什么hibernate不在一个操作中插入所有值?为什么它忽略了“notnull”约束?
请记住,这是一个足够大的项目,所以也许我错过了一些重要的事情在这里。只是尽量让例子简单。

mrwjdhj3

mrwjdhj31#

为什么hibernate会这样做是一个特定于实现的问题。底线是:单表继承中的子属性不允许有NOTNULL约束,hibernate可以在这种假设下自由操作。
当然,原因是与子属性相对应的列必须是 NULL 插入父实体记录时。

相关问题