-->
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.  [ 14 posts ] 
Author Message
 Post subject: Session save with existing id
PostPosted: Sun Apr 29, 2007 12:27 pm 
Newbie

Joined: Sun Apr 29, 2007 12:06 pm
Posts: 5
hello,
i'm using hibernate 3.2.3

here is my code
Code:
   public void insert(User user) {
      session.save(user);
      session.flush();
   }


all is good.

if i try to insert a duplicate record an exception is thrown, as it should be.

the problems is...
the logs show an error.

Code:
ERROR: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)


i managed to trace it to org.hibernate.event.def.AbstractFlushingEventListener:301

here is the code
Code:
   protected void performExecutions(EventSource session) throws HibernateException {

      log.trace("executing flush");

      try {
         session.getJDBCContext().getConnectionManager().flushBeginning();
         // we need to lock the collection caches before
         // executing entity inserts/updates in order to
         // account for bidi associations
         session.getActionQueue().prepareActions();
         session.getActionQueue().executeActions();
      }
      catch (HibernateException he) {
         log.error("Could not synchronize database state with session", he);
         throw he;
      }
      finally {
         session.getJDBCContext().getConnectionManager().flushEnding();
      }
   }


how do i configure hibernate to not log the error, but still throw the exception?
i'm thinking of just modifying log4j.xml to ignore the log, but i think the error is there for a reason and i best find out a way to fix it..

perhaps i should check for existance before saving?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 29, 2007 12:30 pm 
Senior
Senior

Joined: Sat Apr 21, 2007 11:01 pm
Posts: 144
wut?

_________________
Everytime you get an answer to your question without giving credit; god kills a kitten. :(


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 29, 2007 8:44 pm 
Newbie

Joined: Sun Apr 29, 2007 12:06 pm
Posts: 5
i get a stack trace and and exception if i try to save an object with a duplicate primary key...
is there a way just to get an exception and not get a stack trace?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 30, 2007 4:34 am 
Senior
Senior

Joined: Sat Apr 21, 2007 11:01 pm
Posts: 144
You could try not saving duplicate primary keys... the point of a primary key is that it is unique. If you want to update a record you need to get it from the DB first, change some values and then save it back again.
Also if you change:
Code:
log.error("Could not synchronize database state with session", he);

To:
Code:
log.error("Could not synchronize database state with session");

You wont get a stack trace...
I don't really understand the point of what your trying to do. Is this for a production system?

_________________
Everytime you get an answer to your question without giving credit; god kills a kitten. :(


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 30, 2007 10:57 am 
Newbie

Joined: Sun Apr 29, 2007 12:06 pm
Posts: 5
adamgibbons wrote:
You could try not saving duplicate primary keys... the point of a primary key is that it is unique. If you want to update a record you need to get it from the DB first, change some values and then save it back again.
Also if you change:
Code:
log.error("Could not synchronize database state with session", he);

To:
Code:
log.error("Could not synchronize database state with session");

You wont get a stack trace...
I don't really understand the point of what your trying to do. Is this for a production system?


the logging is done with the classes that came with hibernate, so i have no control over them.

the point is: to save a new item to the database, but if the item already exists, throw an exception but don't log the exception because the calling function will do the logging.

no, this is not a production system. i'm tring to learn hibernate.

i'm aware that primary keys are unique. i want my dao to throw an exception when someone (unintentionally) enters a duplicate value for the primary key.

i'm sure you have used hibernate longer than me. on you system, does a session.save(obj) throws an exception as well as logging the exception?

i am new to hibernate, any help is most welcome...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 30, 2007 11:08 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
i want my dao to throw an exception when someone (unintentionally) enters a duplicate value for the primary key.


This is NOT the right way to code ANY application. Do what the previous poster said, check for duplicate values before you try to save.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 30, 2007 11:17 am 
Senior
Senior

Joined: Sat Apr 21, 2007 11:01 pm
Posts: 144
I don't use session.save myself. Your DAO layer should take care of things like that. If you are just starting out learning hibernate I surget you read my comments in these posts:
http://forum.hibernate.org/viewtopic.php?t=973625
http://forum.hibernate.org/viewtopic.php?t=973797

_________________
Everytime you get an answer to your question without giving credit; god kills a kitten. :(


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 13, 2007 1:49 pm 
Newbie

Joined: Mon Apr 16, 2007 5:52 pm
Posts: 13
christian wrote:
This is NOT the right way to code ANY application. Do what the previous poster said, check for duplicate values before you try to save.


I have run into a similar problem for a valid use case, I believe.

If two independent sessions in two threads attempt to save an entity with the same natural key, an error message is always logged because of the log.error call in performExecutions.

Example:

Code:
thread 1                             thread 2

start transaction
check for existence
                                     start transaction
                                     check for existence
                                     save
                                     commit transaction
save
commit transaction

In this scenarion, the commit in thread 1 will cause a ConstraintViolationException and it will always be logged as an error from AbstractFlushingEventListener.performExecutions.

I can deal with the exception, close the session and start a new one in thread 1 and then get the entity back saved by thread 2 and proceed normally, but that error message will be logged.

I assert that a log message at error level should not be logged unconditionally.

Perhaps it can be logged at debug, or a new configuration item could prevent logging that message or dictate what level to log it at?

The other possibility is that there is another way to do what I am trying to do that I am not aware of. I've searched the web and the forums here and did not find any solutions.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 1:15 pm 
Newbie

Joined: Sat Jul 14, 2007 1:41 am
Posts: 6
If you want to show only the exception message in your log file but not the full stack trace, you have to catch the exception and handle it properly. Something like this:

public void insert(User user) {
try {
session.save(user);
session.flush();
}
catch(Exception e) {
log.debug(e.getMessage());
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 1:40 pm 
Newbie

Joined: Mon Apr 16, 2007 5:52 pm
Posts: 13
IgorTN wrote:
If you want to show only the exception message in your log file but not the full stack trace, you have to catch the exception and handle it properly. Something like this:


If you read what I wrote and look at the first post in this thread you will see that the Hibernate code logs the message at error level, unconditionally.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 2:08 pm 
Newbie

Joined: Sat Jul 14, 2007 1:41 am
Posts: 6
Yes, sorry I missed it. From the Hibernate code it follows that you cannot avoid it unless you change it and recompile. The better option would be to do checks from your app, of course, to avoid that exception all together.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 2:33 pm 
Newbie

Joined: Mon Apr 16, 2007 5:52 pm
Posts: 13
IgorTN wrote:
The better option would be to do checks from your app, of course, to avoid that exception all together.


If two sessions are attempting to write the same entity simultaneouly as shown in my example, it is not possible for the application code to check for the existence of the value because another session can save the entity between the time the check and save happens.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 3:28 pm 
Newbie

Joined: Sat Jul 14, 2007 1:41 am
Posts: 6
This sounds as concurrency problem then. The solution would be to make it thread-safe by doing proper synchronization.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 14, 2007 3:34 pm 
Newbie

Joined: Mon Apr 16, 2007 5:52 pm
Posts: 13
IgorTN wrote:
This sounds as concurrency problem then. The solution would be to make it thread-safe by doing proper synchronization.


The example I used showed threads for the sake of simplicity. The two threads could be in different application servers on different machines, in a cluster for example. This is in fact the real deployment we are using. In that case, the synchronization point is the database.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.