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..)
Related
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);
I am trying to build a bidirectional one to many relationship with the spring data jpa but the list annotated with #onetomany always return one element.
Here is the code for my entities(setters and getters omitted):
#Entity
#Table(name = "sdk_sdk")
public class SDKEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String version;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "sdk")
#OrderBy("order ASC")
private List<SDKFileEntity> fileEntities;
}
And the second entity:
#Entity
#Table(name = "sdk_file")
public class SDKFileEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String fileType;
private Integer sdkId;
public SDKFileEntity() {
}
#ManyToOne
#JoinColumn(name = "id", insertable = false, updatable = false)
private SDKEntity sdk;
I am trying to have a manytoone mapping where the sdkId corresponds to the id from the SDKEntity class.
Whenever I try to get the sdkfiles from the sdkEntity using spring's repository, the size of the list is always 1.
So for example:
SDKEntity entity=repository.findOne(foo);
List<SDKFileEntity> files=entity.getFileEntities();
here the size of files is 1, I have to delete the first element from the database to obtain the second element.
For me the reason here was that a parent entity implemented equals and hashcode
and unfortunately in a way that all existing entities were equal.
And non of the child entities implemented it herself.
So then the #OneToMany relation returned only the first element.
Took me quite some time.
This part of Code looks suspicious
#ManyToOne
#JoinColumn(name = "id", insertable = false, updatable = false)
private SDKEntity sdk;
name = "id" it should be actual column name as written in database column name like this
#JoinColumn(name = "VISIT_ID", referencedColumnName = "ID")
#ManyToOne
private Visit visitId;
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!
I am getting violated - parent key not found while trying to save Hibernate Entity
I have parent entity:
#Entity
#Table(name = "parents")
public class Parent implements Serializable {
private static final long serialVersionUID = 1246376778314918671L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "PARENT_ID_SEQ", allocationSize = 1)
#Column(name = "parent_id")
private long parentId;
#Column(name = "display_name")
#Size(min = 1, max = 128)
#NotBlank
private String displayName;
#JsonManagedReference("childAssignments")
#OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval=true)
private Set<ChildAssignment> childAssignments = new HashSet<ChildAssignment>(0);
//regular getters and setters here
}
and child entity looks like (in database it has foreign key on parent_id field from parents table):
Entity
#Table(name = "child_assignments")
public class ChildAssignment implements Serializable {
private static final long serialVersionUID = -5949955576511639261L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "CHILD_ASSIGNMENT_ID_SEQ", allocationSize = 1)
#Column(name = "child_assignment_id")
private long childAssignmentId;
#Column(name = "parent_id")
private long parentId; // getting error because after creating new parent it has not been set
#Column(name = "site_id")
private long siteId;
#ManyToOne
#JoinColumn(name = "parent_id", insertable = false, updatable = false)
private Parent parent;
// regular getters and setters here
}
After parent object and childAssignments object have been created I am adding childAssignment to parent
ChildAssignment ca = new ChildAssignment();
ca.setSiteId(1);
// I do not set parent_id here since I do not know it and expecting Hibernate to figure it out
parent.getChildAssignments().add(childAssignment);
session.save(parent);
Expected result is to save new parent entry with ID and after use this id to save child but seems like hibernate does not know about parent_id at the time of saving, how should I build my association to make it work? or some annotations on parent_id field?
UPDATED
I tried to remove parent_id or set it to #Transient on childAssignment entity, and get new error cannot insert NULL into table, it's obvious that Hibernate is trying to insert parent_id but do not populate it,
setting parent on a child does not help either
ChildAssignment ca = new ChildAssignment();
ca.setSiteId(1);
ca.setParent(parent)
parent.getChildAssignments().add(childAssignment);
session.save(parent);
What I am missing?
SOLVED
I solved a problem changing my childAssignment entity
#Transient -- add transient (just to have it)
#Column(name = parent_id", insertable = false, updatable = false) -- add insertable and updatable both equals to false
private parentId;
.....
#ManyToOne
#JoinColumn(name = "parent_id") -- remove insertable = false, updatable = false options
private Parent parent;
You need to do:
ca.setParent(parent);
as well.
If you specify a two sided relationship then you must assign both sides in Java code, just as you would if it was pure Java.
Secondly, your declaration of a 'parentId' column is redundant. Hibernate will create that for you automatically.
I have a very strange problem with hibernate at the moment.
Somehow on a table, it create a foreign key which reference to itself. the column is also a primary key. This essentially prevent me from delete any row from that table.
In the log I could see a line:
DEBUG org.hibernate.SQL - alter table Device add index
FK79D00A76C682495E (id), add constraint FK79D00A76C682495E foreign key
(id) references Device (id)
Other table with similar table seems fine. and this seems to be true for both MySQL and Derby. I'm using hibernate 4.1.4
the annotated class is as follow.
#Entity(name = "Device")
public class Device extends DomainObject implements Searchable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected long id;
#Column(name = "Type")
#Enumerated(EnumType.STRING)
private DeviceTypeEnum type = DeviceTypeEnum.AccessControlDevice;
#Column(name = "Name", length = Constance.DATABASE_NAME_FIELD_LENGTH)
private String name;
#Column(name = "Description", length = Constance.DATABASE_DESCRIPTION_FIELD_LENGTH)
private String description;
#Column(name = "Identifier", length = Constance.DATABASE_IDENTIFIER_FIELD_LENGTH, unique = true)
private String identifier;
#ManyToMany
#JoinTable(name = "Device2Group", joinColumns = {#JoinColumn(name = "DeviceID")}, inverseJoinColumns = {#JoinColumn(name = "DeviceGroupID")})
private List<DeviceGroup> groups = new ArrayList<DeviceGroup>();
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "location")
private Location location;
#ManyToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "Address")
private Address address;
#ManyToOne
#JoinColumn(name = "Link", nullable = false)
private Link link;
}
It turns out that in one of the Entity Class "Location" which the Device entity references, it has a #ManyToMany mapped collection of Device, where it really should be #OneToMany.
After change the #ManyToMany to #OneToMany the constrain disappears.
I see no references to Device class in your code. So I am assuming that this class has been modified, but its table has not, because it has some data. (Why else should it have a foreign-key to itself?)
Try dropping this table in your database to make hibernate create it once more, or set p.hibernate.hbm2ddl.auto to create-drop.