简体   繁体   中英

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

@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

   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

propostaAcquisto.setCodPropostaEventoPrimaryKey()

before to save the object?
Someone can provide me some examples or documentation links?
Thanks
Regards

For Hibernate 5.x

You can probably use @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 .

For 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 :

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 .

Because you cannot bind the listener to a specific entity, you will have to check the object before applying the change:

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:

org.project.MyIntegrator

You can check the java.util.ServiceLoader JavaDocs for a complete explanation of what's possible to inlcude in the file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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