Java Persistence EntityNotFound Exception on an Object with Embedded Compound PK - java

I'm having some issues with Java Persistence. I've already searched for some answers, and found one where the issue was that a field that could be null was not set to nullable = true. However, that did not seem to work for me.
I will change some names, but try and keep it explained.
This is the exception:
EJB Exception: ; nested exception is: javax.persistence.EntityNotFoundException: Unable to find PersistedObject with id PersistedObjectPK#ec2736; nested exception is: javax.persistence.EntityNotFoundException: Unable to find PersistedObject with id PersistedObjectPK#ec2736
The PersistedObject itself has a Primary Key that is defined as an embedded object with a Compount Primary Key.
#Entity
#Table(name = "DB_TABLE_NAME", schema = "SCHEMA")
public class PersistedObject implements Serializable {
private static final long serialVersionUID = -5823302417440143578L;
#EmbeddedId
private PersistedObjectPK id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_POTATO", insertable = false, updatable = false)
private AnotherPersistedObject anotherPersistedObject;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "ID_CABBAGE", referencedColumnName = "ID_POTATO", insertable = false, updatable = false),
#JoinColumn(name = "CT_CARROT", referencedColumnName = "CT_LETTUCE", insertable = false, updatable = false) })
private OtherPersistedObject otherPersistedObject;
The PersistedObjectPK Class is as follows:
#Embeddable
public class PersistedObjectPK implements Serializable {
private static final long serialVersionUID = 4118584598667509460L;
#Column(name = "ID_POTATO")
private long idLaudo;
#Column(name = "ID_CABBAGE")
private long idTermoApreensao;
#Column(name = "CT_CARROT")
private long ctProduto;
I've already debugged it, the query runs fine directly in the database.
But I cannot find what is causing this error.
The error happens during the Merge operation, after the system requests for the changes to be saved.

I have found the issue.
During the save to database operation.
AnotherPersistedObject term;
//Previously, it did not do thi, it tried saving with the list, then clean and re-insert it.
List<PersistedObject > persistedObjects = term.getList();
term.setList(null);
//After this change, it is now working as excpeted
this.getGenericBO().save(AnotherPersistedObject.class, term, term.getId());
term.setList(persistedObjects);
deleteList(term);
saveList(term);

Related

Mapping two columns in JPA

I have the following 3 tables
table: project
id
company_code
number
contract_type_code
account_type_code
other columns…
table: contract_type
id
company_code
code
name
table: account_type
id
company_code
code
name
The project table references contract_type and account_type tables through contract_type_code/company_code and account_type_code/company_code respectively.
The company_code and code columns are what make a contract_type and account_type unique.
I'm struggling with modelling and mapping this in JPA. I've tried with the #JoinColumn and #JoinColumns annotation and there's no way for me to make it work.
This is one of the ways I've been trying with no success:
public class Project implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long companyCode;
private Long number;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "contract_type_code", referencedColumnName = "code"),
#JoinColumn(name = "company_code", referencedColumnName = "company_code")
})
private ContractType contractType;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "account_type_code", referencedColumnName = "code"),
#JoinColumn(name = "company_code", referencedColumnName = "company_code")
})
private AccountType accountType;
This is the issue I'm getting with the mapping above:
Caused by: org.hibernate.MappingException: Unable to find column with logical name company_code in table contract_type
For this mapping:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "contract_type_code", referencedColumnName = "code", insertable = false, updatable = false),
#JoinColumn(name = "company_code", referencedColumnName = "company_code2", insertable = false, updatable = false)
})
private ContractType contractType;
I get:
Caused by: org.hibernate.DuplicateMappingException: Table [account] contains physical column name [company_code] referred to by multiple logical column names: [company_code], [companyCode]
I assume you have companyCode fields in the AccountType and ContractType. Annotate them as below (first error suggests JPA can't find them):
#Column(name = "company_code")
In your Project class modify companyCode field as follows (to avoid the second error):
#Column(name = "company")
private Long companyCode;
and keep mapping with:
insertable = false, updatable = false
Hope this will help. If not please add AccountType and ContractType classes to your question. Maybe then it will be easier to sort it out

eclipselink manytoone not save

i have a persit problem with elcipselink
here is my model :
#Entity
#Table(name = "TBL_ASSOC_LANGUE_CODE_BE_GARE")
public class AssocLangueCodeBeGare {
#AttributeOverrides({ #AttributeOverride(name = "id_langue", column = #Column(name = "ID_LANGUE") ),
#AttributeOverride(name = "id_gare", column = #Column(name = "ID_GARE") ) })
#EmbeddedId
private AssocLangueCodeBeGareFK key;
#Column(name = "CODE_BE", length = 4)
private String codeBe;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false, name = "ID_GARE", referencedColumnName = "ID_GARE", insertable = false, updatable = false)
private StopPoint stopPoint;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_LANGUE", referencedColumnName = "ID_LANGUE", insertable = false, updatable = false)
private Langue langue;
in StopPoint i don t reference table AssocLangueCodeBeGare, i don t need it.
then when i do :
this.serviceStopPoint.save(currentStopPoint);
for (AssocLangueCodeBeGare assoc : listAssocLangueCodeBeGare) {
assoc.setStopPoint(currentStopPoint);
this.serviceAssocLangueCodeBeGare.save(assoc);
}
save is
#Override
public void save(T entityToSave) {
this.getEntityManager().persist(entityToSave);
}
I m using batch insert for writing and sometimes when i save another entity flush is done and i get :
Caused by: org.h2.jdbc.JdbcBatchUpdateException: NULL not allowed for column "ID_GARE"; SQL statement:
INSERT INTO TBL_ASSOC_LANGUE_CODE_BE_GARE (CODE_BE, ID_GARE, ID_LANGUE) VALUES (?, ?, ?) [23502-192]
at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1208)
at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.executeBatch(DatabasePlatform.java:2134)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeJDK12BatchStatement(DatabaseAccessor.java:871)
does i miss something in the mapping?
does i need to add something like this in stoppoint entity:
#OneToMany(mappedBy = "stopPoint", cascade = CascadeType.ALL)
List<AssocLangueCodeBeGare> assocLangueCodeBeGares;
#EDIT1
I think its caused by my EmbeddedId because it was null!! the mapping does'nt set correct value in the embedable object?
here is the embedable object :
#Embeddable
public class AssocLangueCodeBeGareFK implements Serializable {
private String id_langue;
private Long id_gare;
#Override
public int hashCode() {
thanks a lot!
The insertable = false and updatable = false prevent the value from the mapping from being written to the database. You need to have another mapping to that database column with the value set, or it won't get into the database. While making your OneToMany the ID works, so would the MapsId annotation in the current code as JPA will then set the value in your embeddable ID. Or you could have manually added the value from the referenced class into the appropriate AssocLangueCodeBeGare.key fields.
Finaly i find a solution :
I use #IdClass(AssocLangueCodeBeGareFK.class on AssocLangueCodeBeGare
And i put #id on
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false, name = "ID_GARE", referencedColumnName = "ID_GARE")
private StopPoint stopPoint;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_LANGUE", referencedColumnName = "ID_LANGUE")
private Langue langue;
I rename on my AssocLangueCodeBeGareFK class name of my property to be the same as the AssocLangueCodeBeGare class :
private Long stopPoint;
private String langue;
now all work like a charm.
if it helps...

Hibernate - How to set an object which has pk and fk to be VARCHAR in database?

I have two entities, the first of which is:
#Entity
#Table(name="E_CMS_CFG")
public class E_CMS_CFG extends BaseEntity{
#Id
#OneToOne(cascade=CascadeType.ALL)//, fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "CFG_TYPE", nullable = false, referencedColumnName = "CFG_TYPE", columnDefinition = "VARCHAR(32)"),
#JoinColumn(name = "CFG_TYPE_ID", nullable = false, referencedColumnName = "ID")
})
private E_CMS_CFG_TYPE cfgType;
The second entity is:
#Entity
#Table(name="E_CMS_CFG_TYPE")
public class E_CMS_CFG_TYPE extends BaseEntity{
#Id
#Column(name = "CFG_TYPE", length = 32)
private String cfgType;
In the first entity, I use columnDefinition = "VARCHAR(32)" on the CFG_TYPE column; however, in the database, it is creating a cfg_type integer column. Is it possible to create a VARCHAR cfg_type column and not an integer? And if it is, how? I am using Sqlite 3.8.10.1 version.
UPDATE:
The link did not help, but if I replace in E_CMS_CFG the #Id with #NaturalId (mutable = false), it works, but it creates it without a primary key.
You could try to use the natural id annotation here. For example:
#NaturalId (mutable = false)
#Column(name = "CFG_TYPE", unique = true, nullable = false, length = 32)
private String cfgType;
But I think you would still have to provide an id property and that would still be an integer value/column in your database.
I think this Question is a duplicate of "how to use id with string type in jpa hibernate"
I hope that helps!

Hibernate deletes a record, but the record doesn't go away?

EDIT: Oops, I guess it would help if I posted the delete code. Sorry.
// delete from permanent store and local list
int index = get_record_to_delete();
if (entityList.getEntities().get(index).getEntityId() != null ) {
// existing persisted record
entityService.delete(entityInfo.getEntities().get(index).getEntityId());
}
//remove from local list
entityList.getEntities().remove(index);
return ownersInfo;
// entityService called by above code
public void delete(MyEntity entity) {
repository.delete(entity); // subclass of org.springframework.data.jpa.repository.JpaRepository
}
I'm using Spring Data/JPA V 1.4.2.RELEASE and hibernate 3.6.10.Final.
I have a situation where I'm deleting an entity, and delete appears to work, but when I refresh my web page, the entity reappears. So, it doesn't produce an error, but the record doesn't get deleted.
This entity has child entities contained within it. I suspect that some kind of entity dependence problem is keeping the entity from being truly "deleted", but I don't know which entity dependency it might be, and Hibernate's not telling me. It doesn't matter if the contained entities get deleted or not, but this entity needs to get deleted. Not sure why that's not happening. Here's the entity I'm trying to delete:
public class MyEntity implements java.io.Serializable {
#Id
#GeneratedValue
#Column(name = "MYID", unique = true, nullable = false)
private Long myId;
#Column(name = "MY_NAME", nullable = false, length = 50)
private String myName;
#ManyToOne
#JoinColumn(name = "ADDRESS_ID", nullable = false)
private AddressEntity myAddress;
#ManyToOne
#JoinColumn(name = "OTHER_ADDRESS_ID", nullable = true)
private AddressEntity myOtherAddress;
#ManyToOne
#JoinColumn(name = "TYPE_CODE", nullable = false)
private MyType myType;
#ManyToOne
#JoinColumn(name = "ADDRESS_CODE", nullable = false)
private AddressCode addressCode;
#Column(name = "OTHER", nullable = false, precision = 3, scale = 0)
private Integer myOther;
#ManyToOne
#JoinColumn(name = "PARENT_ID", nullable = false)
private MyParent parent;
#Column(name = "PHONE", nullable = false, precision = 10, scale = 0)
private Long myPhone;
#Column(name = "SOCIAL", nullable = false, length = 9)
private String mySocial;
}
Anyone see anything that might suggest why this entity won't delete?
This turned out to be a case of a Hibernate #OneToMany annotation canceling the delete.
Because the parent object had a #OneToMany(cascade=CascadeType.ALL) annotation on it, like this:
Class MyParent {
#OneToMany(cascade=CascadeType.ALL)
Set<MyObject> myObjects;
}
Hibernate apparently walks the entire object graph and for some reason, because this parent wasn't being deleted, it canceled the child delete.
The thing to do to detect this is turn your logging all the way up to TRACE and look for the following message from Hibernate:
un-scheduling entity deletion
Those are the magic words that let you know that Hibernate is canceling your delete. This was not particularly well documented, so I hope this helps someone else.
In your mapping class use this cascade type. It will delete the records from database.
#OneToMany(cascade=CascadeType.ALL)

Why is this causing java.sql.SQLIntegrityConstraintViolationException?

My app has an entity class (Ativo) with this attribute and JPA annotations:
#JoinColumn(name = "BOLSA", referencedColumnName = "ID")
#ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
private Bolsa bolsa;
When I try to persist the entity class (Ativo), this exception is thrown:
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL131102225757700' defined on 'BOLSA'.
I don't understand what is wrong with my code. Why is it trying to create a new object of type Bolsa if this should be just a foreign key to an existing object??
Header of class Ativo:
#Entity
#Table(name = "ATIVO")
public class Ativo implements EntityInterface<Ativo>, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ID")
private Long id;
#Basic(optional = false)
#Column(name = "CODIGO", unique=true, nullable = false)
private String codigo;
#Basic(optional = false)
#Column(name = "TIPO_MERCADO", nullable = false)
private String tipoMercado;
#Column(name = "DESCRICAO", nullable = false, length = 10000)
private String descricao;
#JoinColumn(name = "BOLSA", referencedColumnName = "ID")
#ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
private Bolsa bolsa;
Header of class Bolsa:
#Entity
#Table(name = "BOLSA")
public class Bolsa implements EntityInterface<Bolsa>, Serializable, Comparable<Bolsa> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ID")
private Long id;
#Basic(optional = false)
#Column(name = "NOME", unique = true, nullable = false)
private String nome;
#Column(name = "DESCRICAO", nullable=false, length = 10000)
private String descricao;
The error message is explicit: you're trying to insert a row with an id that already exists in the data base, hence an integrity constraint violation (a duplicate primary key) ensues.
Check your code, the part where the id is being set, and make sure that it uses an unique identifier. Or use annotations in the id field to auto generate a new key each time. Or define a database sequence to do this.
as suggested in the comments, removing cascade = {CascadeType.PERSIST} from the below relation will work.
#JoinColumn(name = "BOLSA", referencedColumnName = "ID")
#ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
private Bolsa bolsa;
The reason is, Cascade Persist take care of getting things put into the database for you via transitive persistence, so you don't have to explicitly persist the parent (in your case 'Bolsa'). However, it is always your responsibility to maintain the in-memory state of the objects before persisting.
I am suspecting (as it is not clear from the provided snips) that you are explicitly persisting Bolsa object before saving Ativo, so the exception is resolved by removing the cascade persist constraint.
The error message gives you enough information to keep digging:
a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL131102225757700'
It states the it is either a primary key or a unique key constraint, and given the unique-constraints indicated by your mappings (and the fact that I can't see anything wrong with the mappings themselves), I would guess that it a unique key constraint violation, for instance the nome field. But, the error message gives us something more, and that is the name of the constraint that is being violated: SQL131102225757700. So, what you need to do is to figure out which column this constraint applies to, and once you do I'm guessing you will be a lot closer to figuring out the error. (Exactly how to do this depends on your database provider, google it..)

Categories

Resources