Hello Forum,
making my first steps with hibernate I started developing a little knowledge
base application using Java, Swing and of course hibernate. The application has four tables: Users, Categories, Entries and Attachments. The categories and the entries held by the categories are visualized using a subclass of JTree and a subclass of DefaultMutableTreeNode. To prevent users from working on old data that might has been changed by another user I set up a TimerTask and associated an ActionListener on it that shall update the currently expanded node at given intervals. While implementing the code for the ActionPerformed method I encountered the following problem:
I start the application, expand a category and select a node wich is an object of my subclass of DefaultMutableTreeNode and that contains an user object of class Entry. The selected Entry object has the entry_id 2.
After that I change the title of the Entry in the database on the command line using:
UPDATE entry SET entry_title='ChangedValue' WHERE entry_id=2
After that I verified that the row contains the changed data using the PHPMyAdmin tool to look into the table.
The code in the ActionPerformed method of my TimerTask associated ActionListener
shall compare the object in the currently selected node with the one feteched from the databse an replace the object if
it has changed.
Hibernate version:
3.1.1
Mapping documents:
Hibernate config file:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Define Db connection settings -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.username">mainDBUser</property>
<property name="hibernate.connection.password">xxxxxx</property>
<property name="hibernate.connection.url">jdbc:mysql://jupiter.edvbm.local/jkb</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">2</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Define mappings -->
<mapping resource="de/edvbm/jkb/util/data/pojos/Attachment.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/Category.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/Entry.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Mapping file of the Entry class
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.edvbm.jkb.util.data.pojos">
<class name="Entry" table="entry">
<id column="entry_Id" name="entryId" type="long">
<generator class="native"/>
</id>
<property column="entry_created_by_user_Id" length="11" name="entryCreatedByUserId" not-null="true" type="integer"/>
<property column="entry_category_id" length="11" name="entryCategoryId" not-null="true" type="integer"/>
<property name="entryTitle" column="entry_title" length="255" type="string" not-null="true"/>
<property name="entryText" column="entry_text" length="2147483647" type="string"/>
<property name="entryCreationDate" column="entry_creation_date" type="java.util.Date" not-null="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
TreePath currSelectedPath = tree.getSelectionPath();
if (currSelectedPath != null) {
JkbTreeNode currTreeNode = (JkbTreeNode) currSelectedPath.getLastPathComponent();
Object currUserObject = currTreeNode.getUserObject();
if (currUserObject instanceof Entry) {
Session session = context.getSessionFactory().openSession();
// Prevent reading from cache
session.setCacheMode(CacheMode.IGNORE);
Entry entryFromNode = (Entry) currUserObject;
System.err.println("------------------- Loading object from db ---------\n");
Entry entryFromDb = (Entry) session.load(Entry.class, entryFromNode.getEntryId());
if (!entryFromNode.equals(entryFromDb)) {
System.err.println("\n\nNODES ARE NOT EQUAL - Replacing node");
DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
currTreeNode.setUserObject(entryFromDb);
treeModel.reload(currTreeNode);
}
session.close();
} // End if - Instance is of type Entry
}
Full stack trace of any exception that occurs:None
Name and version of the database you are using:MySQL, 5.0.15-nt-max
The generated SQL (show_sql=true):Code:
------------------- Loading object from db ---------
10:24:00,751 DEBUG SessionImpl:1291 - setting cache mode to: IGNORE
10:24:00,751 DEBUG DefaultLoadEventListener:153 - loading entity: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,751 DEBUG DefaultLoadEventListener:230 - creating new proxy for entity
10:24:00,752 DEBUG JDBCContext:215 - after autocommit
10:24:00,752 DEBUG ConnectionManager:305 - aggressively releasing JDBC connection
10:24:00,752 DEBUG SessionImpl:440 - after transaction completion
10:24:00,753 DEBUG SessionImpl:843 - initializing proxy: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,753 DEBUG DefaultLoadEventListener:304 - attempting to resolve: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,754 DEBUG DefaultLoadEventListener:340 - object not resolved in any cache: [de.edvbm.jkb.util.data.pojos.Entry#2]
^^
so it shall be loaded form the databse, or not?
10:24:00,754 DEBUG AbstractEntityPersister:2723 - Fetching entity: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,755 DEBUG Loader:1777 - loading entity: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,756 DEBUG AbstractBatcher:311 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
10:24:00,756 DEBUG ConnectionManager:322 - opening JDBC connection
10:24:00,756 DEBUG DriverManagerConnectionProvider:93 - total checked-out connections: 0
10:24:00,757 DEBUG DriverManagerConnectionProvider:99 - using pooled JDBC connection, pool size: 0
10:24:00,757 DEBUG SQL:346 - select entry0_.entry_Id as entry1_2_0_, entry0_.entry_created_by_user_Id as entry2_2_0_, entry0_.entry_category_id as entry3_2_0_, entry0_.entry_titel as entry4_2_0_, entry0_.entry_text as entry5_2_0_, entry0_.entry_creation_date as entry6_2_0_ from entry entry0_ where entry0_.entry_Id=?
Hibernate: select entry0_.entry_Id as entry1_2_0_, entry0_.entry_created_by_user_Id as entry2_2_0_, entry0_.entry_category_id as entry3_2_0_, entry0_.entry_titel as entry4_2_0_, entry0_.entry_text as entry5_2_0_, entry0_.entry_creation_date as entry6_2_0_ from entry entry0_ where entry0_.entry_Id=?
10:24:00,758 DEBUG AbstractBatcher:424 - preparing statement
10:24:00,759 DEBUG LongType:79 - binding '2' to parameter: 1
10:24:00,764 DEBUG AbstractBatcher:327 - about to open ResultSet (open ResultSets: 0, globally: 0)
10:24:00,765 DEBUG Loader:682 - processing result set
10:24:00,765 DEBUG Loader:687 - result set row: 0
10:24:00,766 DEBUG Loader:1164 - result row: EntityKey[de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,766 DEBUG Loader:1347 - Initializing object from ResultSet: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,767 DEBUG AbstractEntityPersister:1860 - Hydrating entity: [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,767 DEBUG IntegerType:123 - returning '1' as column: entry2_2_0_ <-- CreatedByUserId
10:24:00,768 DEBUG IntegerType:123 - returning '1' as column: entry3_2_0_ <-- CategoryId
10:24:00,770 DEBUG StringType:123 - returning 'OldData' as column: entry4_2_0_ <-- EntryTitle
^^^
Why is it fetching the old data instead of the changed one?
10:24:00,770 DEBUG StringType:123 - returning 'OldData' as column: entry5_2_0_ <-- EntryText
10:24:00,771 DEBUG TimestampType:123 - returning '2006-06-30 10:11:07' as column: entry6_2_0_
10:24:00,772 DEBUG Loader:709 - done processing result set (1 rows)
10:24:00,772 DEBUG AbstractBatcher:334 - about to close ResultSet (open ResultSets: 1, globally: 1)
10:24:00,773 DEBUG AbstractBatcher:319 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
10:24:00,773 DEBUG AbstractBatcher:470 - closing statement
10:24:00,774 DEBUG Loader:839 - total objects hydrated: 1
10:24:00,775 DEBUG TwoPhaseLoad:104 - resolving associations for [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,776 DEBUG TwoPhaseLoad:203 - done materializing entity [de.edvbm.jkb.util.data.pojos.Entry#2]
10:24:00,776 DEBUG StatefulPersistenceContext:820 - initializing non-lazy collections
10:24:00,776 DEBUG Loader:1808 - done entity load
10:24:00,777 DEBUG SessionImpl:292 - closing session
Debug level Hibernate log excerpt:Code:
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
# log4j.rootLogger=DEBUG, stdout
log4j.rootLogger=warn, stdout
#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug
### log cache activity ###
log4j.logger.org.hibernate.cache=debug
When I interpret the log messages correctly they tell me that the object isn't cached anywhere but if so I don't understand why the old data
is returend by the load method.
I searched the web, searched this forum but were unable to find hte reason for the behaviour.
Of course I read the documentation chapters 19.3 and 19.4 about the caches.
But when I get it right any new session has it's own cache - and I create a new session before issuing the load method on it
and I also have set the CacheMode to IGNORE.
Any help would be greatly appreciated.
Have a nice Weekend!
Henning Malzahn