[英]Hibernate import.sql with PostgreSQL repeats primary keys
我在PostgreSQL中使用Hibernate。 創建/驗證架構后,我有一個Hibernate執行的import.sql文件。 內容將相應地導入,但是當我嘗試通過應用程序保留新條目時,Hibernate嘗試使用從1開始自動生成的主鍵,這些主鍵已經被導入文件使用。 有辦法解決嗎?
我有一個所有其他實體都繼承自的實體類,它使用GenerationType.AUTO
或GenerationType.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.