Issue
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
Solution
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.
Answered By - Davide
Answer Checked By - Senaida (JavaFixing Volunteer)