Duplicate entry 'nn' for key '.... ' - java

I'm getting this error quite alot, and my hibernate is acting strange when I try to insert objects into my tables in my mySQL database.
okt. 06, 2015 9:57:28 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1062, SQLState: 23000
okt. 06, 2015 9:57:28 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Duplicate entry '77' for key 'UK_2gy9x2d1hqmk0d77o8ux44c6o'
okt. 06, 2015 9:57:28 PM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
INFO: HHH000010: On release of batch it still contained JDBC statements
org.hibernate.exception.ConstraintViolationException: could not execute statement
When I look in MySQL WOrkbench I can see that whenever I persist or merge I get duplicate rows in my database tables.
I use these two methods for persist and merge:
public void persist(Object entity) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.persist(entity);
session.flush();
session.getTransaction().commit();
}
public void merge(Object entity) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.merge(entity);
session.flush();
session.getTransaction().commit();
}
I got my user class which has a ManyToMany with note class.
#ManyToMany( fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST } )
#JoinTable(
name = "user_note",
joinColumns = {#JoinColumn(name = "empId")},
inverseJoinColumns = {#JoinColumn(name = "note_id")})
private Set<Note> bookmarks = new HashSet<>();
note:
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long projectId;
and a third class which has a OneToMany relation with note.
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
#JoinTable(name = "organisation_note", joinColumns = { #JoinColumn(name = "OrganisationId") }, inverseJoinColumns = { #JoinColumn(name = "note_id") })
private Set<Note> bookmarks = new HashSet<>();
I've been looking around, and can't seem to find any topics on duplicated rows in the database. The first persist won't duplicate the row, but the second will, and the third will throw the exception. After that it's just exceptions after each time I try to persist. Which is not that reliable. Any input is appreciated.

Related

delete children without update them before #OneToMany

I have a problem with hybernate
I have 2 classes like that :
public Class Race {
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="race", orphanRemoval = true)
private List<Lap> laps = new ArrayList<>(0);
...
}
public Class Lap {
#ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.REFRESH)
#JoinColumn(name = "RACE_ID", nullable = false)
private Race race;
#OneToOne(mappedBy = "nextLap", fetch = FetchType.LAZY)
private Lap previousLap;
#OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name = "NEXT_ID")
private Lap nextLap;
...
}
In my database I also have a unique constraint with NEXT_ID and RACE_ID
My problem is when I want to delete my Race, with
txn = session.getTransaction();
txn.begin();
race = session.merge(race);
session.remove(race);
session.flush(); //=>Exception here
txn.commit();
I get the result:
javax.persistence.PersistenceException:
org.hibernate.exception.ConstraintViolationException: could not
execute batch at
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1364)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1347)
at
package.DAORace.deleteRace(DAORace.java:122)
Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint
(LAP_UK1) violated
Hibernate do an update on my lap when I delete the race and my contraint is violated.
My question is how to delete children properly, without update, when I delete parent ?
Note : If I have only one child, I can delete it without any exception, if I have 2 or more children, I have an exception.
Thank you for your help !
For removing entities as a cascade, the best approach is removing them with a few queries.
For example:
em.createQuery("delete from Lap p where p.race.id = :id).setParameter("id", id).executeUpdate();
em.createQuery("delete from Race r where r.id = :id).setParameter("id", id).executeUpdate();
https://thorben-janssen.com/avoid-cascadetype-delete-many-assocations/ read here for better understanding.

Hibernate many to one of the same entity. How to delete?

I have Type class as entity. The Type can have one parent type and many children types.
#Entity
#Table(name = "type")
public class Type extends EntityItem {
...
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "parent_type", referencedColumnName = "id")
private Type parentType;
#OneToMany(mappedBy = "parent_type")
private List<Type> childTypes = new ArrayList<>();
...
}
When I create parent type with children and save them, all is OK. But when I'm trying to delete the parent, I have the error below
2018-08-05 15:58:50,843 INFO [main] impl.TypeServiceImpl (TypeServiceImpl.java:53) - Type delete: Type [id=1000, parentType=null]
Hibernate:
delete
from
type
where
id=?
Aug 05, 2018 3:58:50 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 0, SQLState: 23503
Aug 05, 2018 3:58:50 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ERROR: update or delete on table "type" violates foreign key constraint "fk_gbqg39jytwquch0bjm9j80gsf" on table "type"
Подробности: Key (id)=(1000) is still referenced from table "type".
Could you please explain what is wrong?
Thanks a lot.

Many-to-Many self-reference hibernate annotation(with two entity)

I need help with my application.
I'm using Hibernate+Postgresql + Maven.
And I want to create relation many to many in database without #ManyToMany annotation, but with two #OneToMany annotations, but I have some trouble with it. I have User entity and Friendship entity.
#Entity
#Table(name="USER")
#SuppressWarnings("unused")
public class User {
#Id
#GeneratedValue
#Column(name="USER_ID")
private Long user_id;
#Column(name="NAME")
private String name;
#Column(name="SOURNAME")
private String sourname;
#Column(name="BIRTHDAY")
private String birthday;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user1", cascade= CascadeType.ALL)
private Set<Friendship> friendship = new HashSet<Friendship>(0);
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user2")
private Set<Friendship> friendships = new HashSet<Friendship>(0);
//getters and setters
}
#Entity
#Table(name="FRIENDSHIP")
#AssociationOverrides({
#AssociationOverride(name = "pk.user1", joinColumns = #JoinColumn(name = "user_id")),
#AssociationOverride(name = "pk.user2", joinColumns = #JoinColumn(name = "user_id")) })
#SuppressWarnings("unused")
public class Friendship {
#EmbeddedId
private FriendshipId pk = new FriendshipId();
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CREATED_DATE", nullable = false, length = 10)
private Date createdDate;
public FriendshipId getPk() {
return pk;
}
public void setPk(FriendshipId pk) {
this.pk = pk;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
#Transient
public User getUser1(){return getPk().getUser1();}
#Transient
public User getUser2(){
return getPk().getUser2();
}
public void setUser1(User user1){ getPk().setUser1(user1); }
public void setUser2(User user2){getPk().setUser2(user2);}
}
#Embeddable
public class FriendshipId implements Serializable{
#ManyToOne
private User user1;
#ManyToOne
private User user2;
public User getUser1() {
return user1;
}
public void setUser1(User user1) {
this.user1 = user1;
}
public User getUser2() {
return user2;
}
public void setUser2(User user2) {
this.user2 = user2;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FriendshipId that = (FriendshipId) o;
if (user1 != null ? !user1.equals(that.user1) : that.user2 != null) return false;
if (user2 != null ? !user2.equals(that.user2) : that.user2 != null) return false;
return true;
}
public int hashCode() {
int result;
result = (user1 != null ? user1.hashCode() : 0);
result = 31 * result + (user2 != null ? user2.hashCode() : 0);
return result;
}
}
and I have this stacktrace:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: model.Friendship column: user_id (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:696)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:737)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:493)
at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1324)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
help me!
UPD:
#Entity
#Table(name="FRIENDSHIP")
#AssociationOverrides({
#AssociationOverride(name = "pk.user1", joinColumns = #JoinColumn(name = "user_id_1")),
#AssociationOverride(name = "pk.user2", joinColumns = #JoinColumn(name = "user_id_2")) })
#SuppressWarnings("unused")
public class Friendship
and stacktrace now:
INFO: HHH000227: Running hbm2ddl schema export
Hibernate: alter table FRIENDSHIP drop constraint FK_82a932pmyph72ritrnbumysli
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP drop constraint FK_82a932pmyph72ritrnbumysli
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: constraint "fk_82a932pmyph72ritrnbumysli" in table "friendship" not exist
Hibernate: alter table FRIENDSHIP drop constraint FK_nlu74mncjyeaokaaj0c5eomrp
Hibernate: drop table if exists FRIENDSHIP cascade
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP drop constraint FK_nlu74mncjyeaokaaj0c5eomrp
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: constraint "fk_nlu74mncjyeaokaaj0c5eomrp" in table "friendship" not exist
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: drop table if exists USER cascade
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
Hibernate: drop table if exists USER cascade
ERROR: syntax error (approximate location: "USER")
Position: 22
Hibernate: drop sequence hibernate_sequence
Hibernate: create table FRIENDSHIP (CREATED_DATE timestamp not null, user_id_2 int8, user_id_1 int8, primary key (user_id_1, user_id_2))
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: create table USER (USER_ID int8 not null, BIRTHDAY varchar(255), NAME varchar(255), SOURNAME varchar(255), primary key (USER_ID))
Hibernate: create table USER (USER_ID int8 not null, BIRTHDAY varchar(255), NAME varchar(255), SOURNAME varchar(255), primary key (USER_ID))
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
Hibernate: alter table FRIENDSHIP add constraint FK_82a932pmyph72ritrnbumysli foreign key (user_id_2) references USER
ERROR:syntax error (approximate location: "USER")
Position: 14
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP add constraint FK_82a932pmyph72ritrnbumysli foreign key (user_id_2) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: syntax error (approximate location: "USER")
Position: 103
Hibernate: alter table FRIENDSHIP add constraint FK_nlu74mncjyeaokaaj0c5eomrp foreign key (user_id_1) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP add constraint FK_nlu74mncjyeaokaaj0c5eomrp foreign key (user_id_1) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: syntax error (approximate location: "USER")
Position: 103
Hibernate: create sequence hibernate_sequence
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
I think the problem with this
#AssociationOverrides({
#AssociationOverride(name = "pk.user1", joinColumns = #JoinColumn(name = "user_id")),
#AssociationOverride(name = "pk.user2", joinColumns = #JoinColumn(name = "user_id")) })
You need to use different names for the foreign key columns user_id_1, user_id_2
#AssociationOverrides({
#AssociationOverride(name = "pk.user1", joinColumns = #JoinColumn(name = "user_id_1")),
#AssociationOverride(name = "pk.user2", joinColumns = #JoinColumn(name = "user_id_2")) })
Do not give names to tables like User. User is a reserved keyword in PostgreSQL. Please, use lower case plural names with prefix like xxx_users.
You can take a look on other useful prefixes and naming approaches: StrategyOptions, Hibernate5NamingStrategy.

Double-foreign-key in Hibernate when mapping the same entity twice

It is common practice to map the same entity twice or even thrice, every time with a subset of columns needed for processing. I have found that with Hibernate 3.5.1, every time a #ManyToOne or a #OneToMany exists in two entities mapping the same table, the foreign key is created twice. This has no impact on MySQL and SQL Server, but Oracle refuses the second creation statement.
Here is an example:
#Entity
#javax.persistence.SequenceGenerator(name = "SEQ_STORE", sequenceName = "SEQ_ENTITY")
#Table(name = "ENTITIES")
class Entity {
//All columns
//And then.....
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "BRIDGE_TABLE", joinColumns = { #JoinColumn(name = "ENTITY_ID") }, inverseJoinColumns = { #JoinColumn(name = "ROLE_ID") })
#OrderBy("id DESC")
private Set<Role> roles = new HashSet<Roles>();
}
#Entity
#javax.persistence.SequenceGenerator(name = "SEQ_STORE", sequenceName = "SEQ_ENTITY")
#Table(name = "ENTITIES")
class EntityListItem {
//Only a subset of the previous columns
//And then.....
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "BRIDGE_TABLE", joinColumns = { #JoinColumn(name = "ENTITY_ID") }, inverseJoinColumns = { #JoinColumn(name = "ROLE_ID") })
#OrderBy("id DESC")
private Set<Role> roles = new HashSet<Roles>();
}
Currently, Role is designed not to be navigable to Entity (otherwise I guess there will be 4 foreign keys).
Here are the statement being issued by Hibernate:
create table BRIDGE_TABLE (ENTITY_ID number(19,0) not null, ROLE_ID varchar2(60 char) not null, primary key (ENTITY_ID, ROLE_ID)); //Creates the table
alter table BRIDGE_TABLE add constraint FK47CFB9F0B068EF3F foreign key (ENTITY_ID) references ENTITIES;
alter table BRIDGE_TABLE add constraint FK47CFB9F0B068EF3F foreign key (ENTITY_ID) references ENTITIES;
I'm not sure whether this is a Hibernate bug. We cannot currently move to Hibernate 4. Can be this fixed via code or does it need a new Hibernate version?
I have made a workaround:
Add a #ForeignKey annotation with the same FK name to both entities (e.g. #ForeignKey(name = "FK_TO_ENTITY", inverseName = "FK_TO_ROLE"))
Extend LocalSessionFactoryBean like the following:
#override
public void createDatabaseSchema() throws DataAccessException
{
logger.info("Creating database schema for Hibernate SessionFactory");
SessionFactory sessionFactory = getSessionFactory();
final Dialect dialect = ((SessionFactoryImplementor) sessionFactory).getDialect();
final LinkedHashSet<String> sql = new LinkedHashSet<String>();
for (String query : getConfiguration().generateSchemaCreationScript(dialect))
sql.add(query);
HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.execute(new HibernateCallback<Void>()
{
#Override
public Void doInHibernate(Session session) throws SQLException
{
session.doWork(new Work()
{
#Override
public void execute(Connection conn) throws SQLException
{
PhoenixAnnotationSessionFactoryBean.this.executeSchemaScript(conn, sql.toArray(new String[0]));
}
});
return null;
}
});
}
Reason: the #ForeignKey annotation ensures that the FKs will have the same name, hence the SQL statements will be equal each other. The overriden LSFB will store the SQL queries needed to create the schema in a Set so that no duplicate will be allowed.

SQLGrammarException: No value specified for parameter 1 with criteria

1-1 association:
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "messageDetails")
public MessageEntry getMessageEntry() {
return messageEntry;
}
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public MessageDetails getMessageDetails() {
return messageDetails;
}
Want to load dependent entry in stateless session:
MessageDetails messageDetails =
(MessageDetails) sess.createCriteria(MessageDetails.class)
.add(Restrictions.eq("messageEntry", messageEntry))
.uniqueResult();
I get
Exception in thread "main" org.hibernate.exception.SQLGrammarException: No value specified for parameter 1
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:122)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
The SQL is not what I want. May be I don't understand something?
03:21:13,274 DEBUG SQL:104 - /* criteria query */ select this_.id as id11_0_, this_.date as date11_0_, this_.messageId as messageId11_0_, this_.replyTo as replyTo11_0_, this_.subject as subject11_0_ from MessageDetails this_ where this_.id=?
I want to select MessageDetails by its property messageEntry, isn't that possible? Thanx.

Categories