[英]Persisting Map<Entity, Integer> with @ElementCollection (JPA)
[英]Issue in persisting entity with @EmbeddedId and @ElementCollection in Postgres using Hibernate
我想使用Hibernate在Postgres 9上執行CRUD操作。
實體:
@Entity
@Table(name = "MESSAGE_HISTORY_RECORD")
public class MessageHistoryRecord {
@EmbeddedId
private MessageCompoundKey compoundKey;
@Column
private String responseChannel;
@ElementCollection
private List<Trace> traces;
@Column
private byte[] payload;
//getters and setters
}
復合ID實體:
@Embeddable
public class MessageCompoundKey implements Serializable {
private static final long serialVersionUID = 9084329307727034214L;
@Column
private String correlatedMsgId;
@Column
private String messageId;
@Column
private String endpointId;
//getters and setters
}
ElementCollection實體:
@Embeddable
public class Trace implements Serializable{
private static final long serialVersionUID = 9084329307727034214L;
private Long timestamp;
private String description;
//getters and setters
}
我正在使用hibernate.hbm2ddl.auto=update
為我創建架構。
它為我創建了表格:
CREATE TABLE "public"."message_history_record"
(
correlatedmsgid varchar(255) NOT NULL,
endpointid varchar(255) NOT NULL,
messageid varchar(255) NOT NULL,
payload bytea,
responsechannel varchar(255),
CONSTRAINT message_history_record_pkey PRIMARY KEY (correlatedmsgid,endpointid,messageid)
)
;
CREATE UNIQUE INDEX message_history_record_pkey ON "public"."message_history_record"
(
correlatedmsgid,
endpointid,
messageid
)
;
CREATE TABLE "public"."messagehistoryrecord_traces"
(
messagehistoryrecord_correlatedmsgid varchar(255) NOT NULL,
messagehistoryrecord_endpointid varchar(255) NOT NULL,
messagehistoryrecord_messageid varchar(255) NOT NULL,
description varchar(255),
timestamp bigint
)
在持久化任何對象時,我在messagehistoryrecord_traces
表中未找到任何條目。
休眠屬性:
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.connection.url=jdbc:postgresql://192.xx.xx.xx:5432/testdb
hibernate.connection.username=***
hibernate.connection.password=****
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.pool_size=10
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
堅持sql:
休眠:插入MESSAGE_HISTORY_RECORD(有效負載,responseChannel,relatedMsgId,endpointId,messageId)值(?,?,?,?,?)
根據您的配置,默認值應適用於收集表的表名,列名和連接列名。 這些默認值的構造如下:
表名:引用實體的名稱,后跟一個下划線,以及包含元素名稱的實體屬性的名稱( MessageHistoryRecord_traces
)
連接列:引用實體的名稱,后跟一個下划線以及實體表的主鍵列的名稱。
僅當您在父實體中只有一個主鍵字段而不是您的情況時,才允許使用第二種情況。 因此,您可以自己指定聯接列,如下所示(我對集合表名稱和外鍵列名稱進行了重命名,因為它們對於我的數據庫系統來說太長了):
@ElementCollection
@CollectionTable(name = "mhr_traces",
joinColumns={@JoinColumn(name="mhr_correlatedmsgid", referencedColumnName="correlatedmsgid"),
@JoinColumn(name="mhr_endpointid", referencedColumnName="endpointid"),
@JoinColumn(name = "mhr_messageid", referencedColumnName = "messageid")})
private List<Trace> traces = new ArrayList<>();
還有一件事情:您還必須為主鍵類實現equals()
和hashCode()
方法hashCode()
如果您尚未這樣做,則它們不可見)。
您的表創建腳本還缺少外鍵definitino(如果不是自動生成的,則手動添加它們):
CONSTRAINT mrFK FOREIGN KEY (mhr_correlatedmsgid, mhr_endpointid, mhr_messageid) REFERENCES MESSAGE_HISTORY_RECORD (correlatedmsgid,endpointid,messageid)
根據您的數據庫語法進行調整(我不知道PostgreSQL)
通過這些調整,一切都對我有效; 實際上是在Oracle數據庫系統上,而EclipseLink作為持久性提供程序。 我認為這不是特定於實現的
您是否在跟蹤列表中添加了任何內容或該內容為空? 它對我使用postgresql沒有任何調整。 將hbm2ddl.auto設置為update時,hibernate也創建了表以及它們之間的外鍵關系。 這是我使用的示例代碼:
public class App
{
public static void main( String[] args )
{
System.out.println("Maven + Hibernate + Postgresql");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
MessageCompoundKey cKey = new MessageCompoundKey();
cKey.setCorrelatedMsgId("correlatedMsgId_2");
cKey.setEndpointId("endpointId_2");
cKey.setMessageId("messageId_2");
MessageHistoryRecord record = new MessageHistoryRecord();
record.setResponseChannel("ArsenalFanTv");
List<Trace> traces = new ArrayList<>();
Trace t1 = new Trace();
t1.setDescription("description_1");
t1.setTimestamp(System.currentTimeMillis());
traces.add(t1);
Trace t2 = new Trace();
t2.setDescription("description_2");
t2.setTimestamp(System.currentTimeMillis());
traces.add(t2);
record.setCompoundKey(cKey);
record.setTraces(traces);
session.save(record);
session.getTransaction().commit();
}
}
我的配置文件(hibernate.cfg.xml)如下:
<hibernate-configuration>
<session-factory>
<!-- <property name="hibernate.bytecode.use_reflection_optimizer">false</property> -->
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.password">****</property>
<property name="hibernate.connection.url">jdbc:postgresql://127.0.0.1:5432/testdb</property>
<property name="hibernate.connection.username">****</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="com.skm.schema.MessageHistoryRecord"></mapping>
</session-factory>
</hibernate-configuration>
我正在使用StatelessSession而不是session 。 根據文檔:
無狀態會話不會實現一級緩存,也不會與任何二級緩存交互,也不會實現事務后寫或自動臟檢查,也不會將操作級聯到關聯的實例。 無狀態會話將忽略集合 。 通過無狀態會話執行的操作會繞過Hibernate的事件模型和攔截器。 由於缺少一級緩存,無狀態會話很容易受到數據別名的影響。
可以在此線程上找到更多詳細信息。
在使用Session而不是StatelessSession之后,它起作用了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.