-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Duplicate key or integrity constraint violation
PostPosted: Sat Dec 24, 2005 10:21 pm 
Newbie

Joined: Sat Dec 24, 2005 10:04 pm
Posts: 4
Hi
I am new to Hibernate and I would like to persist a list of tags/words that i get from an XML file. I have a POJO (with id,tag) for a Tag and use the generator to automatically assign the id

<id
name="id"
column="TAG_ID">
<generator class="increment"/>
</id>

<property
name="tag"
column="TAG"
node="tag"
not-null="true"
unique="true"/>

<property
name="count"
column="COUNT"
not-null="true"
unique="false"/>


The problem is that I would like to have the word to be unique. ie do not insert if already present. If I try to

currentSession.save(tag1);

And a tag with the same name is already present. I get a "Duplicate key or integrity constraint violation" ConstraintViolationException (stacktrace below).

In order to avoid this I tried to use:

Tag tag1 = (Tag) currentSession.createQuery("from Tag as Tag where Tag.tag like :tagString")
.setParameter("tagString", tagString)
.uniqueResult();

if (tag1 == null){
// tag is new
currentSession.saveOrUpdate(tag);
} else {
// update count
}

Which would have been alright, but I need to do this for over 10 million tags, which is gonna be inefficient.

I am wondering if someone can help me with what is the correct way to map this.

There is another thing I read about "business keys" and have appropriately implemented the equals and hashcode in the TAG POJO, but I am not sure how to check it the tag is already presisted.

Alternatively is it that I need to use composite-id? In which case it seems like I would not be able to use the <generator class="increment"/>.

It seems to me like there might be an easy way to do this and I am just missing some detail here.
I would appreciate any help or pointers to examples.
Thanks
Akshay





Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
3.1
Mapping documents:

Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:
] Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
[java] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
[java] at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
[java] at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
[java] at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:230)
[java] at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
[java] at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
[java] at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
[java] at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
[java] at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
[java] at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
[java] at edu.umbc.weblog.feed.WeblogManager.testTag(Unknown Source)
[java] at edu.umbc.weblog.feed.WeblogManager.main(Unknown Source)
[java] Caused by: java.sql.BatchUpdateException: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'Akshay' for key 2"
[java] at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1540)
[java] at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
[java] at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
[java] ... 9 more

Name and version of the database you are using:
MySQL
The generated SQL (show_sql=true):
create table TAG (
[java] TAG_ID bigint not null,
[java] TAG varchar(255) not null unique,
[java] COUNT bigint not null,
[java] primary key (TAG_ID)
[java] )
Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 26, 2005 10:31 am 
Regular
Regular

Joined: Wed Dec 21, 2005 6:57 pm
Posts: 70
Here are a few approaches, but it depends on your situation (how many words, how often, how many repeats, etc.):

1) check if it exists before you do it (as you suggest in your question)

2) handle the exception from the DB when there is a clash

3) use the word as the primary key -- since it must be unique, this will cause Hibernate to update the existing record (if necessary) when you encounter the same word again.

4) manage some cache of words yourself, to reduce explicit DB checks. The trick there is to not try to cache all 10 million words.

More details about your situation may help us answer.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 26, 2005 9:27 pm 
Newbie

Joined: Sat Dec 24, 2005 10:04 pm
Posts: 4
hi damonf
Thanks for the reply!
Basically what I am trying to do is read a bunch of xml files and dump them into the database (I have about 10 million XML nodes that need to be updated into the DB)

Basically it seems like there are following alternatives:

damonf wrote:
Here are a few approaches, but it depends on your situation (how many words, how often, how many repeats, etc.):

1) check if it exists before you do it (as you suggest in your question)

Tag tag1 = (Tag) currentSession.createQuery("from Tag as Tag where Tag.tag like :tagString")
.setParameter("tagString", tagString)
.uniqueResult();

if (tag1 == null){
// tag is new
currentSession.saveOrUpdate(tag);
} else {
// update count
}


2) handle the exception from the DB when there is a clash

try {
tx = currentSession.beginTransaction();

currentSession.saveOrUpdate(tag);
tx.commit();
} catch (ConstraintViolationException e){
if (tx!=null) tx.rollback();
// update the count
}

3) use the word as the primary key -- since it must be unique, this will cause Hibernate to update the existing record (if necessary) when you encounter the same word again.

I am not sure if I would like to do this - since I would like the wordID to be the unique identifier. But I am not sure how to make the word part of the composite key while using the <generator class="native"> option

4) manage some cache of words yourself, to reduce explicit DB checks. The trick there is to not try to cache all 10 million words.

Hmm, i guess this could also be a way - but I dont think I land up doing it in this fashion just because words is not the only table I am updating in the application.

Additionally the other approach seems to be to use criteria and expression, altho I am not sure what the performance implications of using this are like: But in any case presently i think I am using this approach.

Tag tag = (Tag) currentSession.createCriteria(Tag.class)
.add(Expression.like("tag",tagString))
.uniqueResult();

if tag == null then create new tag instance else update the count and
currentSession.saveOrUpdate(tag);
tx.commit();

So, do you think that using this would be better in terms of performance than say using HQL??

Thanks once again for your time
Akshay



Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 27, 2005 10:02 am 
Regular
Regular

Joined: Wed Dec 21, 2005 6:57 pm
Posts: 70
I'm not sure which query style is faster. I assume native SQL is fastest, so if you need to performance tune you can try that.

There are a few ways to query for number of matching rows here: http://www.hibernate.org/118.html#A2


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.