簡體   English   中英

使用Hibernate在Postgres中使用@EmbeddedId和@ElementCollection持久化實體的問題

[英]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)值(?,?,?,?,?)

根據您的配置,默認值應適用於收集表的表名,列名和連接列名。 這些默認值的構造如下:

  1. 表名:引用實體的名稱,后跟一個下划線,以及包含元素名稱的實體屬性的名稱( MessageHistoryRecord_traces

  2. 連接列:引用實體的名稱,后跟一個下划線以及實體表的主鍵列的名稱。

僅當您在父實體中只有一個主鍵字段而不是您的情況時,才允許使用第二種情況。 因此,您可以自己指定聯接列,如下所示(我對集合表名稱和外鍵列名稱進行了重命名,因為它們對於我的數據庫系統來說太長了):

@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.

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