简体   繁体   English

Hibernate映射与ID触发器+序列生成的ID

[英]Hibernate mapping with ID generated by DB trigger + sequence

everyone. 大家。 I've a LOG table with a combination of trigger and sequence to create the id, so when I insert the line I do not have to specify the id, otherwise the database returns error. 我有一个带有触发器和序列组合的LOG表来创建id,所以当我插入行时,我不必指定id,否则数据库会返回错误。 However Hibernate claims (rightly) that was specified primary key. 然而,Hibernate声称(正确地)指定了主键。

What kind of "generator" property should I use in this case? 在这种情况下我应该使用什么样的“发电机”属性?

I already tried " assigned " it says: 我已经尝试过“ 分配 ”它说:

org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save (): it.m2sc.simulator.beans.Log

With " select " hib ask me the natural key, but there is no natural key in this table, but the primary. 用“ select ”hib问我自然键,但是这个表中没有自然键,但是主键。

org.hibernate.id.IdentifierGenerationException: no natural-id property defined; need to specify [key] in generator parameters

That's my hbm 那是我的朋友

<hibernate-mapping>
    <class name="it.m2sc.simulator.beans.Log" table="LOG">
        <id name="id" type="integer" column="LOG_ID" access="field">
            <generator class="select" /> 
        </id>
        <property name="date" type="date" column="LOG_DATE" access="field" />
        <property name="user" type="string" column="LOG_USER" access="field" />
        <property name="evtId" type="integer" column="EVT_ID" access="field" />
        <property name="detail" type="string" column="LOG_DETAIL" access="field" />
        <property name="deleted" type="character" column="LOG_DELETED" access="field" />
        <property name="codiceRaggruppamento" column="LOG_CODICE_RAGGRUPPAMENTO" type="string" access="field" />
    </class>
</hibernate-mapping>

The Class 班级

public class Log {
    private Integer id;
    private Date date;
    private String user;
    private Integer evtId;
    private String detail;
    private Character deleted = '0';
    private String codiceRaggruppamento;

    ... ( getter & setter )
}

DDL of table/trigger/sequence 表/触发器/序列的DDL

CREATE TABLE
    LOG
    (
        LOG_ID NUMBER(12) NOT NULL,
        LOG_DATE TIMESTAMP(6),
        LOG_USER VARCHAR2(50),
        EVT_ID NUMBER(12),
        LOG_DETAIL VARCHAR2(100),
        LOG_DELETED CHAR(1) DEFAULT '0 ' NOT NULL,
        LOG_CODICE_RAGGRUPPAMENTO NCHAR(2) NOT NULL,
        CONSTRAINT LOG_PK PRIMARY KEY (LOG_ID),
        CONSTRAINT LOG_CFG_EVENT_TYPE_FK1 FOREIGN KEY (EVT_ID)
        REFERENCES CFG_EVENT_TYPE (EVT_ID)
    );

   CREATE SEQUENCE  LOG_SEQ  MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 358 CACHE 20 NOORDER  NOCYCLE;

CREATE OR REPLACE TRIGGER "DTCUSR"."LOG_TRG" BEFORE INSERT ON LOG
FOR EACH ROW
BEGIN
  <<COLUMN_SEQUENCES>>
  BEGIN
    IF :NEW.LOG_ID IS NULL THEN
      SELECT LOG_SEQ.NEXTVAL INTO :NEW.LOG_ID FROM DUAL;
    END IF;
  END COLUMN_SEQUENCES;
END;

Ah, just fyi: db is Oracle11 啊,只是fyi:db是Oracle11

Ty in advice Ty建议

sequence-identity id generation strategy embeds sequence call directly in the insert statement: sequence-identity id生成策略直接在insert语句中嵌入序列调用:

insert into log (log_id, log_date, log_user, ...)
values (LOG_SEQ.nextval, ?, ?, ...)

This way you can get rid of the trigger because it's not needed. 这样你就可以摆脱触发器,因为它不需要。

Also, you have to set hibernate.jdbc.use_get_generated_keys property to true , so that Hibernate reads the generated keys after executing insert statements. 此外,您必须将hibernate.jdbc.use_get_generated_keys属性设置为true ,以便Hibernate在执行insert语句后读取生成的键。

In hbm.xml: 在hbm.xml中:

<id name="id" type="integer" column="LOG_ID" access="field">
  <generator class="sequence-identity" >
    <param name="sequence">LOG_SEQ</param>
  </generator>
</id>

With annotations: 带注释:

@Entity
@Table(name = "LOG")
public class Log {
  @Id
  @org.hibernate.annotations.GenericGenerator(name="logSequenceGenerator", strategy = "sequence-identity",
    parameters = {@org.hibernate.annotations.Parameter(name="sequence", value="LOG_SEQ")})
  @GeneratedValue(generator = "logSequenceGenerator")
  @Column(name = "LOG_ID")
  private Integer id;
  ...
}

Take a look at this link explaining how to use a trigger based generator. 请查看此链接,了解如何使用基于触发器的生成器。

Additionaly, remember to use the hibernate.jdbc.use_get_generated_keys property in your Hibernate persistence configuration 另外,请记住在Hibernate持久性配置中使用hibernate.jdbc.use_get_generated_keys属性

<property name="hibernate.jdbc.use_get_generated_keys" value="true" />

Probably you will get an NullPointerException while inserting using the class described on the link. 使用链接中描述的类插入时,可能会出现NullPointerException。 Change the method executeAndExtract(PreparedStatement insert, SessionImplementor session) to anything like this 将方法executeAndExtract(PreparedStatement insert,SessionImplementor session)更改为这样的任何内容

    @Override
    protected Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session)  throws SQLException {

        insert.executeUpdate();

        try {

            ResultSet rs = insert.getGeneratedKeys();
            rs.next();

            return rs.getLong(1);

        } catch (RuntimeException rt) {
            throw new SQLException("Error while attempt to use the CustomTriggerGenerator. Check the <property name=\"hibernate.jdbc.use_get_generated_keys\" value=\"true\" /> in your persistence.xml");      
        }

    }

Hibernate doc is really clear on different generation mechanism available. Hibernate doc对于可用的不同生成机制非常清楚。 Depending on how data will be written one should make a call: 根据数据的编写方式,应拨打电话:

For simple use cases you might use sequence , but there are several more options available. 对于简单的用例,您可以使用sequence ,但还有其他几个选项可用。

Refer: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-id 参考: http//docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-id

If you want your ID to be generated only in database and just read by hibernate you can use parameters 'insertable' and 'updatable' in @Column annotation: 如果您希望仅在数据库中生成ID并且只是通过hibernate读取,则可以在@Column注释中使用参数“insertable”和“updatable”:

@Column(name = "LOG_ID", insertable=false, updatable=false)
private Integer id;

With this parameters hibernate will not add the id column to inserts and updates. 使用此参数,hibernate不会将id列添加到插入和更新中。

To achieve the goal you need to use GenerationType.IDENTITY 要实现此目标,您需要使用GenerationType.IDENTITY

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "LOG_ID", updatable = false, nullable = false)
private Integer id;

See more on https://www.thoughts-on-java.org/jpa-generate-primary-keys/ 有关详细信息,请访问https://www.thoughts-on-java.org/jpa-generate-primary-keys/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM