簡體   English   中英

Hibernate import.sql與PostgreSQL重復主鍵

[英]Hibernate import.sql with PostgreSQL repeats primary keys

我在PostgreSQL中使用Hibernate。 創建/驗證架構后,我有一個Hibernate執行的import.sql文件。 內容將相應地導入,但是當我嘗試通過應用程序保留新條目時,Hibernate嘗試使用從1開始自動生成的主鍵,這些主鍵已經被導入文件使用。 有辦法解決嗎?

我有一個所有其他實體都繼承自的實體類,它使用GenerationType.AUTOGenerationType.IDENTITY 他們兩個都不起作用:

@MappedSuperclass
public class Entidade implements Serializable {
    private static final long serialVersionUID = -991512134416936719L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    public Entidade() {
    }

    public Entidade(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

這是我的persistence.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="...">
        <jta-data-source>...</jta-data-source>
        <class>...</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="create-drop" />
            <property name="hibernate.default_schema" value="jcat" />
            <property name="hibernate.hbm2ddl.import_files_sql_extractor"
                value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.hbm2ddl.import_files" value="import.sql" />
            <property name="hibernate.c3p0.min_size" value="5" />
            <property name="hibernate.c3p0.max_size" value="20" />
            <property name="hibernate.c3p0.max_statements" value="50" />
            <property name="hibernate.c3p0.timeout" value="3000" />
            <property name="hibernate.c3p0.idle_test_period" value="1800" />
        </properties>
    </persistence-unit>
</persistence>

Hibernate可能使用了一個稱為hibernate_sequence的全局數據庫范圍的序列。 您也可以將其導入其他數據庫。 您可以在hibernate_sequence中將具有較大id值的insert語句添加到腳本中。

請在SQL日志中查看Hibernate是否使用hibernate_sequence

更新
@DouglasDeRizzoMeneghetti的一些附加說明

我照你說的做了,奏效了。 FK變為整數,可以為空,現在我在數據庫中只有一個序列,而不是每個ID都有一個序列。 我發現,即使聯接表也創建了自己的序列,因此通過使用單個序列,所有內容都變得更加整潔和井井有條。

事實證明,PostgreSQL的列具有“串行”數據類型,基本上是與序列關聯的整數數據類型。 該序列由DBMS自動創建和處理。 為了強制Hibernate創建這樣的列類型,可以使用@Column(columnDefinition = "serial")注釋,如下所示:

@Id
@Column(columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

請注意,雖然序列用於生成ID,但我沒有使用strategy = GenerationType.SEQUENCE ,因為這將告訴Hibernate創建自己的hibernate_sequence並在所有表中使用它,我試圖避免這種行為。 生成序列的名稱遵循${tablename}_${column_id_name}_seq ,例如'client_id_seq'。 然后,我可以在導入腳本中省略ID的硬編碼插入,因此:

insert into schema.table (id, name) values (1, 'John');

成為:

insert into schema.table (name) values ('John');

而且,當將實體保留在我的Web應用程序中時,Hibernate會自動為每個表使用正確的順序,因此我不再有關於重復值的問題。

另一個貢獻是,如果您有一個@MappedSuperclass在其ID列中使用上述注釋,則所有子類都會自動創建自己的序列,因此不必為每個實體都執行此操作。 我唯一看到的缺點是,雖然我有一個在MariaDB下可運行但在PostgreSQL下不起作用的注釋,但現在我有一個在MariaDB上不起作用的注釋,因為我不記得它具有@Column(columnDefinition = "serial")強制。 從數據庫進行抽象和分離的工作量很大。

編輯:此策略提出了另一個問題。 我的PK是串行類型的,這一事實使Hibernate將其對應的FK創建為串行。 由於串行類型在PostgreSQL中不能為空,因此我的實體之間沒有可選的關系。 我最終使用了@ v.ladynev提出的解決方案,在我的實體ID中使用了GenerationType.SEQUENCE並為hibernate_sequence設置了一個較高的起始值,然后插入測試數據

這樣,FK變成了可以為空的整數,現在我在數據庫中只有一個序列,而不是每個ID都有一個序列。 我發現,即使聯接表也創建了自己的序列,因此通過使用單個序列,所有內容都變得更加整潔和井井有條。 謝謝。

您在postgres中的ID列的數據類型應該是串行的

比使用此注釋

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

暫無
暫無

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

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