New entity persisted with NULL id (id=0) - oracle10g

I'm using Hibernate 4.3.11.
I have the following entity:
#Entity
#Table(name="ESP_RETARD")
public class ESP_RETARD implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "pk_seqret", sequenceName = "ESP_RETS_SEQ1", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk_seqret")
#Column(nullable = false)
#NotNull
private long idRetard;
I tried to persist a new entity on ESP_RETARD.
But, I encounter a problem: a new entity is added, however, it's with id 0.
the second time to add a new one, I got this exception:
javax.persistence.PersistenceException:
org.hibernate.exception.ConstraintViolationException: could not
execute statement
...
Caused by: org.hibernate.exception.ConstraintViolationException: could
not execute statement
...
Caused by: java.sql.SQLException: ORA-00001: unique constraint
(EDTINGA.SYS_C009525) violated
Knowing that: when I used:
Hibernate 3 with
those jars,
I didn't get this issue.
But once I upgraded to Hibernate 4.3.11 with those jars, I encountred this excpetion.
==> So it's a problem of jars, I suppose that it's missed jar(s) have to be added to Hibernate 4.3.11.
Have you please any idea about solving that issue ?.
Big thanks Sir.

You can try removing the entire entity and then re-create it with new table name and new column name for the id.
Don't forgot to change the nomination on #SequenceGenerator and #GeneratedValue.
Indeed, it's not necessary to use neither #Column(nullable = false) nor #NotNull.
#Id
#SequenceGenerator(name = "pk_seqret1", sequenceName = "RETS_SEQ1", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk_seqret1")
private long idRetard;
HTH.

Related

Hibernate ignores the schema name while calling nextval() - from postgres 12

My pojo definition worked fine till I used Postgres 9.x, When I changed the database to postgres 12 I get Sequence not found error when inserting a new row to a table. When I debugged the sql statements run in the database I found that hibernate ignored the schema name.
Postgres 9 : select nextval('ita.ita_settings_is_is_id_seq')....
Postgres 12: select nextval('ita_settings_is_is_id_seq')....
My Pojo definition is as follows
#Entity
#Table(name = "ita.ita_settings_is")
#SequenceGenerator(name = "settingItaIdSeq", sequenceName = "ita.ita_settings_is_is_id_seq", initialValue = 1, allocationSize = 1)
public class itaSettings implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "settingitaIdSeq")
#Column(name = "is_id")
private int id;

JPA entity sequence generating

In spring boot JPA I tried to implement sequence generator but it is not working.
the following is my entity
#Entity
#Table(name = "role_level")
public class RoleLevel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "role_level_sequence", sequenceName = "role_level_id_seq",allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "role_level_sequence")
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "role_level")
private String roleLevel;
#Column(name = "role_level_description")
private String roleLevelDescription;
//getters and setters
}
when I insert value in directly through the database then next sequence from the db is not getting in jpa.it shows
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "role_level_pkey"
Detail: Key (id)=(7) already exists.
But the console shows
Hibernate: select nextval ('role_level_id_seq')
I think its not working.
Is there any solution for this.?

Hibernate #Column annotation cannot mapping to database

I have a Entity in Spring Boot and PostgreSql, I'm using #Column annotation to mapping to database. This is my Entity snip code :
#Entity(name = "users")
#Table(name = "users", schema = "public")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 12355345L;
#Id
#Column(name = "user_id")
private String userid;
#Column(name = "user_name")
private Integer username;
When id run and test with postman, i get an error :
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: column users0_.usersid does not exist
Hint: Perhaps you meant to reference the column "users0_.user_id".
I don't know why. How to resolve this ?
There are couple of things for your info.
1) Need to check your spring.jpa.hibernate.ddl-auto property as depends on that property, the database tables, columns will be populated by Hibernate.
2) Next drop the existing table and change the value as spring.jpa.hibernate.hbm2ddl.auto=update so that it will create/update table according to the annotations provided in the entity class
3) Remove unnecessary annotations. Following is enough.
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#Column(name = "user_id")
private String userid;
................

jpa, eclips-link 2.5.1: OneToMany not working on columns not primary key

I have these two entities:
Anagrafica
#Entity
#Access(AccessType.FIELD)
#Table(name = "S_MC_CC_USER")
#SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_ID", allocationSize = 1)
public class Anagrafica implements Serializable{
private static final long serialVersionUID = 332466838544720886L;
#EmbeddedId
private AnagraficaId anagraficaId;
#Column(name = "USER_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID")
private Long userId;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "USER_ID", updatable = false, insertable = false)
private List<Mobile> mobiles;
/**
* La classe di dominio che modella la chiave primaria di un {#link Anagrafica}
*
* #author Massimo Ugues
*
*/
#Embeddable
static public class AnagraficaId implements Serializable {
private static final long serialVersionUID = -54640203292300521L;
#Column(name = "ANAG_UTENTE")
private String bt;
#Column(name = "COD_ABI")
private String abi;
public AnagraficaId() {
super();
}
Mobile
#Entity
#Table(name = "S_MOBILE")
#SequenceGenerator(name = "SEQ_MOBILE", sequenceName = "SEQ_MOBILE", allocationSize = 1)
public class Mobile implements Serializable{
private static final long serialVersionUID = 5999493664911497370L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_MOBILE_DEVICE_REGISTRY")
#Column(name = "ID_MOBILE")
private Long mobileId;
#Column(name = "DEVICE_TOKEN")
private String deviceToken;
#Column(name = "DATA_INSERIMENTO")
#Temporal(TemporalType.TIMESTAMP)
private Calendar dataInserimento = Calendar.getInstance();
With eclispe-link 2.1.2 all works great, but with eclispe-link 2.5.1 I got this exception:
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [persistence-unit] failed.
Internal Exception: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field mobiles] from the entity class [class com.intesasanpaolo.domain.entities.sub.Anagrafica] is incomplete. When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns. Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:1954)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1945)
at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(PersistenceProvider.java:322)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:288)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 40 more
The problem is the OneToMany association based on a foreign key that is not primary key.
Since I cannot change the database model how can I make it work?
Kind regards
Massimo
The reason it worked in a prior version was that it EclipseLink doesn't look at the fields in the mapping, but with JPA adding derived Id support, EclipseLink now validates the number of foreign keys match the number of ID fields.
James' answer here
JPA #JoinColumn issues while joining on non primary key columns
explains it that you'll need to use a descriptorCustomizer to change the JPA mapping. So you would either not map the field in JPA (mark it as #Transient) and then add a mapping in the customizer, or have the JPA mapping to use all primary key fields and then change the mapping in the customizer to only use the USER_ID->USER_ID fields.
EclipseLink customizers are shown here:
http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_customizer.htm
Ok, this is the Customizer I created:
public void customize(ClassDescriptor descriptor) throws Exception {
// handle the oneToManyMapping to non foreign keys
ManyToManyMapping mapping = (ManyToManyMapping) descriptor.getMappingForAttributeName("mobileDevices");
ExpressionBuilder builder = new ExpressionBuilder();
mapping.setSelectionCriteria(builder.getField("USER_ID").equal(builder.getParameter("USER_ID")));
// handle the insert statement
mapping.setInsertCall(new SQLCall(""));
}
As suggested from Chris this works great with the selection.
I had to modify the Insert Call since eclipse-link tried to create and insert statement on a mapping table that I haven't.
The problem now is on the delete: when I try to delete the collection from the source association (i.e. Cliente) as described here
Cliente.ClienteId id = new Cliente.ClienteId(abi, bt);
Cliente cliente = clienteRepository.findOne(id);
cliente.setMobileDevices(null);
I need eclipse link to delete the orphan.
The dml generated is the following:
DELETE FROM S_MC_CC_CLIENTI_S_MOBILE_DEVICE_REGISTRY WHERE ((mobileDevices_ID_MOBILE_DEVICE_REGISTRY = 13) AND ((ANAG_UTENTE = '71576493') AND (COD_ABI = '01025')))
Since I haven't the mapping table I modified the customizer adding a setDeleteCall statement :
mapping.setDeleteCall(new SQLCall("DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE USER_ID = #USER_ID"));
In this way eclipse link generates 2 dml:
DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE USER_ID = NULL
DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE (ID_MOBILE_DEVICE_REGISTRY = 13)
The first is the translation of my SQLCall, but without the correct parameter: any idea how to generate only the correct delete statement?
Kind regards.
Massimo

merging entity with onetomany mapping and #version field causes delete of the previous mapping

Hi! All,
I have a mapping issue with two entities. mapped through a #OneToMany unidirectional relation. I have an entity Artifact which can have multiple Revision. Here's how I have mapped them
#Entity
#Table(name = "artifact")
public class Artifact implements Serializable {
private static final long serialVersionUID = 248298400283358441L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Version
private Integer version;
...
#OneToMany(cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE })
#JoinTable(name = "artifact_revisions", joinColumns = #JoinColumn(name = "artifact_id"), inverseJoinColumns = #JoinColumn(name = "revision_id"))
private Set<Revision> revisions;
And the revisions entity
#Entity
#Table(name = "revision")
public class Revision implements Serializable {
private static final long serialVersionUID = -1823230375873326645L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
#Column(name = "date_created", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
The revision table saves the filed name that was updated; old value and new value etc.
The problem I face is that when I update the artifact; the last mapping gets deleted and then it inserts a new one, so if effect I only have the last but one revision available not the entire revision history.
Hibernate:
update
artifact
set
description=?,
estimate=?,
name=?,
rank=?,
status=?,
sysId=?,
version=?
where
id=?
and version=?
Hibernate:
delete
from
artifact_revisions
where
artifact_id=?
and revision_id=?
Hibernate:
insert
into
artifact_revisions
(artifact_id, revision_id)
values
(?, ?)
If I remove #version annotation from the artifact it works fine.
Is it because I am mapping the relation in a wrong manner? Should this relation be mapped as an element collection instead?
There is another Entity Task which is to be mapped with the Revision entity. So what will be the best approach here?
Maybe this is not a straight answer to your question but I think you should look into hibernate envers. I think it's doing pretty similar thing. (envers stands for entity versioning). You just annotate entity with #Audited put some listeners into config and the rest magic is done for you.