【问题标题】:Issue in persisting entity with @EmbeddedId and @ElementCollection in Postgres using Hibernate使用 Hibernate 在 Postgres 中使用 @EmbeddedId 和 @ElementCollection 持久化实体的问题
【发布时间】:2016-07-18 11:24:59
【问题描述】:

我想使用 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:

Hibernate:插入 MESSAGE_HISTORY_RECORD(payload、responseChannel、relatedMsgId、endpointId、messageId)值(?、?、?、?、?)

【问题讨论】:

    标签: java hibernate orm


    【解决方案1】:

    根据您的配置,默认值应适用于集合表的表名、列名和连接列名。这些默认值的构造如下:

    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() 方法(它们在您的帖子中不可见),您必须实现。

    您的表创建脚本也缺少外键定义(如果没有自动生成,请手动添加):

    CONSTRAINT mrFK FOREIGN KEY (mhr_correlatedmsgid, mhr_endpointid, mhr_messageid) REFERENCES MESSAGE_HISTORY_RECORD (correlatedmsgid,endpointid,messageid)
    

    调整它以匹配您的数据库语法(我不知道 PostgreSQL)

    通过这些调整,一切都对我有用;确实在 Oracle 数据库系统和 EclipseLink 作为持久性提供者上。我认为这不是特定于实现的

    【讨论】:

    • 我实现了equals()hashcode()。问题在于 StatelessSession 的使用。
    【解决方案2】:

    您是否在跟踪列表中添加了任何内容或者它是空的? 它对我使用 postgresql 没有任何调整。随着 hbm2ddl.auto 设置为更新,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 的使用。
    【解决方案3】:

    我使用的是 StatelessSession 而不是会话。根据文档:

    无状态会话不实现一级缓存,也不与任何二级缓存交互,也不实现事务性后写或自动脏检查,也不将操作级联到关联的实例。 无状态会话会忽略集合。通过无状态会话执行的操作绕过 Hibernate 的事件模型和拦截器。由于缺少一级缓存,无状态会话容易受到数据别名效应的影响。

    更多详情可以在thread找到。

    在使用 Session 而不是 StatelessSession 之后,它起作用了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      • 2010-11-24
      • 2011-03-18
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2016-04-01
      相关资源
      最近更新 更多