簡體   English   中英

為什么 Hibernate 忽略非空約束?

[英]Why Hibernate ignores not-null constraint?

我遇到過有趣的 Hibernate 行為。 有人可以解釋我為什么會發生這種情況嗎?

技術棧:Java 11 / Spring boot [2.3.2.RELEASE] / Spring data [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> {
}

所以當我試圖保存 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 日志,我看到休眠插入“名稱”、“姓氏”和空值。 之后,我關閉了“es_identification”列上的非空約束,我看到 Hibernate 首先插入“名稱”、“姓氏”、空值,然后更新“es_identification”並設置相應的值。

所以這對我來說看起來很奇怪。 為什么 Hibernate 不會在一個操作中插入所有值? 為什么它忽略“非空”約束?

請記住,這是一個足夠大的項目,所以也許我在這里錯過了一些重要的事情。 只是試圖使示例盡可能簡單。

為什么Hibernate 會這樣做是一個特定於實現的問題。 底線是:單表繼承中的子屬性不允許非空約束,並且 Hibernate 可以在該假設下自由運行。

原因當然是在插入父實體記錄時,子屬性對應的列必然為NULL

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM