aspose file tools*
The moose likes Object Relational Mapping and the fly likes Strange DB behavior w/hibernate Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Strange DB behavior w/hibernate" Watch "Strange DB behavior w/hibernate" New topic
Author

Strange DB behavior w/hibernate

Steven Bell
Ranch Hand

Joined: Dec 29, 2004
Posts: 1071
I'm using hibernate with a MySQL DB. I have three classes and three tables. I have written a test to test save and get of one of the classes, the Person class. Here is the code for the test.

here is the code for the save and search methods.

The test passes, and the person object I created and passed into the save method is returned from the search, but no person is saved in the database. Even if I pause the program in between the save and search, and go look at the database there is nothing there (using MySQL Command Center and MySQL Query Browser).

Any ideas? I can't even think of a wild guess on this one.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
just a guess: try using show_sql=true and watch what's going on


java amateur
Steven Bell
Ranch Hand

Joined: Dec 29, 2004
Posts: 1071
I have done that and it shows the insert and select statements (although it doesn't show the parameters, just '?', but that is normal of hibernate).

Using the same configuration code I am able to drop and recreate the tables.

Also I manually put a person into the db and am able to retrieve it.

I'm really confused at this point.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
i'm no expert at all, much more of the opposite; one Q i'v in mind for sme time is why some use t.commit() while others s.flush() (without transaction)

and i�m saying this because you do it the other way i do
Steven Bell
Ranch Hand

Joined: Dec 29, 2004
Posts: 1071
I don't understand it, but using t.commit() instead of s.flush() works!!!

You rock! Thanks alot.
Sathya Srinivasan
Ranch Hand

Joined: Jan 29, 2002
Posts: 379
In order to save or update something in the database, the session must be inside a Transaction and you must commit the Transaction. The commit() method is the one that actually asks the database to commit the transaction. Session.save() just issues the statement to the database without asking to commit it. That's why you can do rollback() on transactions.

Session.flush() clears the state of the Session itself (which is essentially the state of all the objects that the session had been tracking). It by itself does not do any commits.


Cheers, Sathya Srinivasan - SCJP 1.2, SCWCD 1.2, SCMAD 1.0
Co-Author of Whizlabs SCMAD Certification Exam Simulator and SCMAD Exam Guide Book
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
@Sathya
thanks for clearing that out!

anyway, when you say:
In order to save or update something in the database, the session must be inside a Transaction

if i do it like this:

suggests i'm using Transaction inside Session
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
The session is used to read and write objects using select, insert, update, and delete. The transaction is used to either commit or rollback any changes made via the session.

The session holds the connection to the database, and the transaction holds a reference to the session so it can use the same connection and tell the session to flush when you commit the transaction. Think of the transaction more as a transaction manager. The real transaction lives only in the database, and the database uses it to hide not-yet-committed changes from other connections.

Also, your exception handling is actually swallowing any Hibernate exceptions. Instead of catching HibernateException and printing the stack trace, let it propagate from your save() and search() methods to the caller. The caller can then handle it. As it's written, save() will never throw HibernateException. If an error occurs, only the console will tell you. The calling code will think everything worked. Simply remove the catch blocks from your DAO methods.

It appears you're using JUnit for your tests. If that's the case, you're writing far too much code. JUnit is already set up to catch unexpected exceptions and fail the test. After removing the DAO catch blocks, you can rewrite your test like this:You could also add a DBManager class member to the test case and set it using DBManager.getInstance() in its setUp() method. Not a big deal, but it would allow you to factor that all up into a common BaseDBManagerTest superclass.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
David
your post deserves very close atention from me; pls let me start from the end:

You could also add a DBManager class member to the test case and set it using DBManager.getInstance() in its setUp() method. Not a big deal, but it would allow you to factor that all up into a common BaseDBManagerTest superclass

pls let me know if this is somehow close to what you where expecting:

test runs ok

i've been trying to understand factory patterns (because of this) and after reading B Eckel's TIP (thinking in patterns) and also this i came to the conclusion that the simplest solution would would be enough for me (Eckel's first example):


but you made me arise a doubt: doing it my way i've to set a @param, but in your example you dont:

my code:

am i talking about something completely diferent?
(for one reason the answer is yes - maybe i should open another thread)

i had no time to fully study your other ideas; i'll be back as soon as i can

thank you very much for your ideas
Steven Bell
Ranch Hand

Joined: Dec 29, 2004
Posts: 1071
The thing that was really throwing me off is in another app I was just using session.save(), session.flush(), and then session.close() and it was (actually still is) working fine.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
i continue this conversation here and here too
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by Steven Bell:
The thing that was really throwing me off is in another app I was just using session.save(), session.flush(), and then session.close() and it was (actually still is) working fine.
Does this other application use the non-transactional tables type of MySQL? The InnoDB tables are transactional, meaning until you commit other transactions won't see changes, but I don't remember the name of the older table type. ISAM? Anyway, if that other application is so simple it doesn't do any rollbacks, it's unlikely that you'd notice any trouble.
[ March 27, 2005: Message edited by: David Harkness ]
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Miguel, your TesteFactory example is exactly what I was suggesting. I got it from the XP Cookbook chapter on JUnit, I think. That's the safest route as each test method gets a new TesteFactory instance. If setUp() creates all new objects, there's no chance of one test affecting another. However, if the objects you're creating have no state except a database connection like DAOs, there's a way to have setUp() called only once, speeding up your tests.

You extend TestCase, provide a static suite() method to create a TestSuite, and store your DAO and other objects in static variables.I just noticed that the exception code I was talking about was Steven's, not yours. Sorry folks! So the DBManager.getInstance() was not mine, but I'm familiar with the pattern.

You can have each interface have its own factory class. This removes the need for the "type" parameter. It also decouples the DAOs. Your example would like this this:Obviously, you'd replace System.getProperty() with whatever configuration class you use. On a side note, this is one big piece that Spring replaces with XML files.

So yes, we're talking about the same thing -- just a different way to do it.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
at a first sight looks like BaseDao would replace advantageously Factory, but i'd to check

as to junit:
MockLookupTableFactory
HibernateAuditInterceptor
auditor

sounds completely strange to me, sorry
you'r of great help, thanks!
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by miguel lisboa:
MockLookupTableFactory
HibernateAuditInterceptor
auditor

sounds completely strange to me, sorry
Hibernate allows you to register a single Interceptor with a Session instance. When the session is flushed, all new and modified objects are passed one-by-one to the callback methods in the interceptor, allowing you to alter them further if you like. My HibernateAuditInterceptor sets createdDate and modifiedDate appropriately.

The Interceptor uses a SystemClock; in this case a standard version that uses System.currentTimeMillis() without alteration. Other versions I created for doing time-sensitive testing are Fixed, Shifted, and Random (for fun). This allows me to have the application work as if in the past or future without having to actually change my computer's clock.

I created a LookupTable class for things generic lookup tables (code -> text, 120001 -> "Male"), for example sexes (male, female, unspecified), states, countries, user status, etc. The LookupTableRegistry manages the entire set for the application, and MockLookupTableFactory.register() registers a mock registry that creates mock lookup tables that consider all values valid and convert codes to their text representation using Integer.toString(). I guess it's more like a faux (or stub) registry rather than a mock since it's not used to validate the method calls it receives.

All in all, it's specific to my application's setup and can be safely ignored.
Steven Bell
Ranch Hand

Joined: Dec 29, 2004
Posts: 1071
Originally posted by David Harkness:
Does this other application use the non-transactional tables type of MySQL? The InnoDB tables are transactional, meaning until you commit other transactions won't see changes, but I don't remember the name of the older table type. ISAM? Anyway, if that other application is so simple it doesn't do any rollbacks, it's unlikely that you'd notice any trouble.

[ March 27, 2005: Message edited by: David Harkness ]


I think that is correct. That makes more sense now.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Strange DB behavior w/hibernate
 
Similar Threads
Trouble inserting with Hibernate2 and newer MySQL
hibernate
Hibernate : Could not execute query -- Exception
Refresh issue for hibernate session
Help me to Update only selected Fields and not all the columns in database through hibernate ??