简体   繁体   English

hibernate中复合键的自动生成

[英]Automatic generation of composite key in hibernate

Good morning.早上好。
I have a db table with a composite primary key.我有一个带有复合主键的数据库表。 This is the create statement of the table这是表的create语句

CREATE COLUMN TABLE "ACQUISTO_EVENTI"(
"COD_PROPOSTA_EVENTO" VARCHAR(100) NOT NULL,
"COD_PROPOSTA" INTEGER CS_INT,
"ID_EVENTO" INTEGER CS_INT,
"TIPO_OPERAZIONE" VARCHAR(100),
    ... others fields...
PRIMARY KEY (
    "COD_PROPOSTA_EVENTO"
)

The composite primary key formula is复合主键公式为

COD_PROPOSTA_EVENTO = "COD_PROPOSTA" + _ + "ID_EVENTO"

To save the data on the db I created the following POJO object为了将数据保存在数据库中,我创建了以下 POJO object

@Entity
@Table(name = "ACQUISTO_EVENTI")
@JsonIgnoreProperties(ignoreUnknown = true)
public class PropostaAcquisto implements Serializable {
    
    private static final long serialVersionUID = -5977779326596870770L;

    public PropostaAcquisto() {
        super();
    }
    
    @Id 
    @Column(name = "COD_PROPOSTA_EVENTO", length=100)
    private String codPropostaEventoPrimaryKey;
    
    @Column(name = "COD_PROPOSTA")
    private Integer codProposta;        
    
    @Column(name = "ID_EVENTO")
    private Integer idEvento;   
    
    @Column(name = "TIPO_OPERAZIONE", length=100)
    private String tipoOperazione;
    
        ... others fields...

    public Integer getCodProposta() {
        return codProposta;
    }

    public void setCodProposta(Integer codProposta) {
        this.codProposta = codProposta;
    }

    public Integer getIdEvento() {
        return idEvento;
    }

    public void setIdEvento(Integer idEvento) {
        this.idEvento = idEvento;
    }
    
    public String getCodPropostaEventoPrimaryKey() {
        return codProposta + "_" + idEvento;
    }

    public void setCodPropostaEventoPrimaryKey(String codPropostaEventoPrimaryKey) {
        this.codPropostaEventoPrimaryKey = codProposta + "_" + idEvento;
    }
    
    public String getTipoOperazione() {
        return tipoOperazione;
    }

    public void setTipoOperazione(String tipoOperazione) {
        this.tipoOperazione = tipoOperazione;
    }

            ... others getter and setters...
}

When I try to save an object with the following code当我尝试使用以下代码保存 object

   public Object saveOrUpdate() {
        PropostaAcquisto propostaAcquisto = new PropostaAcquisto();
        propostaAcquisto.setCodProposta(1);
        propostaAcquisto.setIdEvento(1);

        Transaction transaction = null;
        try {
            if (session == null || ! session.isOpen()) {
                session = HibernateFactory.getSessionFactory().openSession();
            } 
            transaction = session.beginTransaction();
            session.saveOrUpdate(obj);
            transaction.commit();
        } catch (JDBCException e) {
            System.out.println("Dettaglio errore >>> "+e.getSQLException().getMessage());
            obj = null;
        } finally {
            if (session != null) {
                session.close();
            } 
        }
        return obj;
    }

I get the following error我收到以下错误

Exception in thread "main" org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): PropostaAcquisto

There is a way to automatic generete the primary key with Hibernate without to call directly有一种方法可以使用 Hibernate 自动生成主键,而无需直接调用

propostaAcquisto.setCodPropostaEventoPrimaryKey()

before to save the object?在保存 object 之前?
Someone can provide me some examples or documentation links?有人可以为我提供一些示例或文档链接吗?
Thanks谢谢
Regards问候

For Hibernate 5.x对于 Hibernate 5.x

You can probably use @PrePersist :您可能可以使用@PrePersist

@Entity
@Table(name = "ACQUISTO_EVENTI")
@JsonIgnoreProperties(ignoreUnknown = true)
public class PropostaAcquisto implements Serializable {

    @PrePersist
    public void createKey() {
        this.codPropostaEventoPrimaryKey = this.codProposta + "_" + this.eventoId;
    }

}

See the Hibernate ORM documentation for more info about JPA Callbacks . 有关 JPA 回调的更多信息,请参阅 Hibernate ORM 文档。

For Hibernate ORM 4.3.x对于 Hibernate ORM 4.3.x

If you are using an older version of Hibernate ORM, you can probably achieve the same registering an event listener on the EventType.PERSIST :如果您使用的是旧版本的 Hibernate ORM,您可能可以在EventType.PERSIST上实现相同的注册事件监听器:

public class MyIntegrator implements org.hibernate.integrator.spi.Integrator {

    public void integrate(
            Configuration configuration,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {

        final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );

        // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an
        // implementation of the org.hibernate.event.service.spi.DuplicationStrategy contract like this
        eventListenerRegistry.addDuplicationStrategy( myDuplicationStrategy );

        // This form adds the specified listener(s) to the beginning of the listener chain
        eventListenerRegistry.prependListeners( EventType.PERSIST, new CreatePKBeforePersist() );
}

Where CreatePKBeforePersist is a class implementing PersistEventListener .其中CreatePKBeforePersist是实现 PersistEventListener 的PersistEventListener

Because you cannot bind the listener to a specific entity, you will have to check the object before applying the change:因为您无法将侦听器绑定到特定实体,所以您必须在应用更改之前检查 object:

public class CreatePKBeforePersist implements PersistEventListener {

    public void onPersist(PersistEvent event) throws HibernateException {
        if (event.getObject() instanceof PropostaAcquisto) {
            PropostaAcquisto pa = (PropostaAcquisto) event.getObject();
            pa.createKey();
        }
    }

    ...
}

This article explains how you can register an integrator : 本文介绍了如何注册集成商

Add a text file in:在以下位置添加文本文件:

/META-INF/services/org.hibernate.integrator.spi.Integrator

the file will contain only the full name of your class:该文件将仅包含 class 的全名:

org.project.MyIntegrator

You can check the java.util.ServiceLoader JavaDocs for a complete explanation of what's possible to inlcude in the file.您可以查看java.util.ServiceLoader JavaDocs 以获取文件中可能包含的内容的完整说明。

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

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