FAQs from the Forum
How do I set a many-to-one association to an Entity having a composite id?
I have weird behavior or Exceptions when using a many-to-one association to an Entity having a composite id?
<composite-id ...>
<column name="id1" .../>
<column name="id2" .../>
</composite-id>
and in the other class
<many-to-one ...>
<column name="id1" .../>
<column name="id2" .../>
</many-to-one>
Be sure to keep columns in the exact same order between composite-id columns and many-to-one keys.
Do I have to keep the Session open if I want to use lazy initalization?
Pick one: - Have to keep the Session open (several strategies) until all lazily loaded collections/proxies have been loaded because they have been called.
- Eagerly fetch all required data with an HQL query before closing the Session.
- Reattach, by calling lock() or update() (see the API documentation) a Detached Object (you don't have to do anything special for that) to a new (second) Session when a view that is rendered accesses a lazily loaded property.
- Initialize all (by the specific application use case) required lazy collections and proxies manually with initialize() before you close the Session.
Most applications use the first three, the last option is useful in special cases.
Will Tiger / new JDK 1.5 features be used in Hibernate ?
Take it easy :) We're thinking on that for Hibernate3. Generics are promising, an Metadata annotation layer is on progress into HibernateExt (CVS). But Hibernate will stay backward compatible.
When will the book "Hibernate in Action" be available ?
The authors are currently finishing the book, it will be available in the 2nd quarter 2004. Chapters are provided earlier in the Manning Early Access Program (you pay for a subscription to the draft chapters as they go to production and receive a print copy when it is available). Some chapters may be available on TheServerSide (for a period of time).
Using join fetch returns duplicate parent, is it expected ?
Yes. It's intentional as that's how the semantics are for joins in the relational algebra. Distinct your parent objects in your java code.
Can I rollback after a session.flush() ?
Definitely YES! Flushing the session means executing SQL like you do in plain JDBC. It has absolutely no relationship with transaction. Actually Hibernate can flush session behind your back.
Storing Big5 or Unicode Strings
Data has some String fields that stores Chinese Big5 encoding String , ex: Title and Description; I use DAO pattern , and in the implementation code , when persisting 'Data', I have to manually change the String encoding from Big5 to 8859_1 to be able to store it to MySQL. I found the final solution: In hibernate.cfg.xml:
<property name="connection.url">jdbc:mysql://host/db?useUnicode=true&characterEncoding=Big5</property>
Both useUnicode = true , and characterEncoding=Big5 are needed and make sure to 'escape' the '&' character.
I've got problems with legacy tables with UPPERCASE/lowercase identifiers
You can easily quote the table names in the mapping file, using backticks:
<class table="`TableName`" ..... >
MS SQL Server / JSQLConnect driver - SQL update or deletion failed (row not found)
Hibernate 2.0.1 propagates an exception from Session.flush() following Session.delete(Object):
net.sf.hibernate.HibernateException: SQL update or deletion failed (row not found)
at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:25)
NonBatchingBatcher.addToBatch expects PreparedStatement.executeUpdate() to return 1, but it returns 0 in this case, even though it has deleted 1 row from the database. I solved this problem by appending "/lastUpdateCount=true" to the JDBC url for JSQLConnect. This makes the JDBC driver behave as Hibernate expects. Without this property, it seems the driver returned the number of rows updated by a trigger that was executed as a side-effect of the requested change. See http://www.j-netdirect.com/JSQLConnect/TechnicalReference.html#ConnectSettings for more information.
Should I GROUP BY all object attributes in HQL?
At present you need to explicitly enumerate all the employee properties in the GROUP BY. This might be a wrinkle in HQL, or it might actually be OK.
SELECT e
FROM Employee e
LEFT JOIN Customer c AS c.staff.id
WHERE e.team.id = :id
GROUP BY e.firstName, e.lastName, e.salary
ORDER BY count(c.staff.id) ASC
"Flush during cascade is dangerous" with own equals() method
When you delete child object from collection like described in documentation and - Use proxy for you persistent class
- Override equals method for your class
- Use class comparison checking in your equals() like this
if( !(o.getClass() == getClass()) ) return false;
You may get an error because both classes are not identical. Use instanceof instead.
How to handle transactions that span multiple data access objects?
Consider a business controller that needs to delegate to 2 DAOs for a certain use case. The processing is supposed to occur within a single transaction. How to inform your DAOs that they need to participate in the surrounding transaction, instead of opening their own Hibernate Session? And how to make them run in their individual transactions else? Passing around a Session instance as parameter to the DAO methods is not desirable, as such a required parameter is inconvenient, and the DAO interfaces should not be Hibernate-specific. A RYO solution according to the ThreadLocal Session pattern will work but tie the business controllers to Hibernate for transaction demarcation. The goal is to make DAO interfaces agnostic of both the data access mechanism of an implementation and the actual transaction strategy of the caller. This allows for e.g. mixing Hibernate DAOs and plain JDBC DAOs with either native Hibernate transactions or JTA. A generic transaction mechanism is needed, with support for passing thread-bound Hibernate Sessions or JDBC Connections or whatever. The Spring Framework provides such generic transaction management in a very lightweight way, with first-class support for Hibernate, backed by either native transactions or JTA. There is also respective support for JDO and plain JDBC. Transactions can be demarcated either programmatically or declaratively via an AOP interceptor. The generic management helps to avoid tying business objects to a particular transaction strategy. Furthermore, Spring's lightweight bean container offers means for wiring up an application, e.g. a middle tier that consists of business objects, data access objects, and resources. Spring also provides generic AOP support within the bean container, and sophisticated convenience support for plain JDBC access. Note that Spring's individual parts can be reused on their own easily, as they are as loosely coupled as possible. Data Access with the Spring Framework
What is the precedence for the methods in the Lifecycle and Interceptor interfaces?
Save or Update: Save: - Lifecycle.onSave
- Interceptor.onSave
Update: Load: - Interceptor.onLoad
- Lifecycle.onLoad
Delete: - Interceptor.onDelete
- Lifecycle.onDelete
Flush: - Interceptor.preFlush
- Interceptor.findDirty
- Interceptor.onFluchDirty
- Interceptor.postFlush
MS SQL performance and unicode (indexing of VARCHARs)
Am I the only person in the world who didn't know what happens if you use VARCHAR's with Java and the MS SQL JDBC driver? It seems unlikely because I can find no mention of this in the list archives or the like. If you use VARCHARs for database tables and index those columns either (as a primary key or not) , then you will find that without this option sendStringParametersAsUnicode=false set on the JDBC driver string, all queries will use a table scan rather than the index to access rows. This is somewhat annoying with large tables (as you can imagine). The reason is that the JDBC driver marks the string as an NVARCHAR so when the execution plan is created, it includes the conversion of the row's VARCHAR to an NVARCHAR. This stops SQL Server from using an index and you end up with a very slow query. What gets even more annoying (and potentially confusing) is that this does not happen with direct queries, only prepared statements (hence the issue with hibernate). It might be wise to make note of this fact in the FAQ or documentation. I only found 1 article on google in a news group that mentions this (and I am indebted to that person for enlightening me...) The article: on Google Groups From: Gary Evesson <gevesson@decentrix.com>
I'm getting a java.lang.ExceptionInInitializerError or java.lang.NoSuchMethodError (from HSQLCaseFragment.toFragmentString()) with JDK 1.3
Hibernate is build with the latest stable JDK 1.4, this error may be a binary incompatibility with JDK 1.3. Recompile the hibernate.jar (ant jar) with JDK 1.3. The first one looks like a combination/issue with both Tomcat and the JDK. Here's the old thread: http://sourceforge.net/forum/message.php?msg_id=2062040 The second one can be reproduce in a standalone environment (tested on 1.3.1_07, eclipse, HSQLDB and joined-subclass) If anyone is able to reproduce and debug this issue, please add to this FAQ entry.
Follow up: Hi, we are a develop team at Universidad de las Americas, Puebla in Mexico and we got the same problem trying to run a web app using hiberante, the app was developed using JSDK 1.4, but in the real enviroment it was suposed to run on a JSDK 1.3, all we did to get it running was: 1) upgraded to the last stable version of the 1.3 platform 2) recompiled the hiberante source with this version (all though any 1.3 version seems to do fine) 3) get the apropiate jdbc drivers for the jsdk and database and that's it, the app is running on a JSDK 1.3 enviroment using all the virtuous functions in hibernate :)
I'm getting "Too many tables. MySQL can only use 31 tables in a join"
You can set outer-join="false" on associations or, in Hibernate 2.1, use hibernate.max_fetch_depth.
Websphere 5 produces a com.ibm.websphere.ce.cm.StaleConnectionException: Connection is closed
Unfortunately on WebSphere 5.0 I get the following error message when closing a Hibernate Session: net.sf.hibernate.util.JDBCExceptionReporter TRAS0014I: The following exception was logged com.ibm.websphere.ce.cm.StaleConnectionException: Connection is closed We had this same problem with data source connections in Websphere. We "fixed" it by configuring the data source to "Disable auto connection cleanup". It's a checkbox in the data source setup in Websphere.
What are the rules for the SQL String passed in the new createSQLQuery"
There is an excellent thread about this, see http://forum.hibernate.org/viewtopic.php?t=418 Rules: #01: All of the columns must be specified, either via {alais1}.* or by explicitly listing each. [to be continued]
Hibernate crashes on this Sun RAQ server. What gives?
The problem with most Sun RAQs is that they are loaded with pretty old (and I guess stable) versions of Java (version 1.3 is old now, OK?!). The problem here is related to a FAQ above in that you get some really odd null pointer exceptions, e.g. when creating the session factory or when hydrating a rowset back into an object. The solution is simple: rebuild hibernate with a similar version of Java to the one on the server. In most cases this is just a case of installing the old version of Java and then setting JAVA_HOME to point to the old Java before running the hibernate build script (shipped with the distribution). From: Russ Freeman <russ@freesoft.co.uk>
Invalid parameter exceptions listed when an object mapping is read
Although the documentation suggests that object properties can be public, private or protected, there is still a restriction on accessing non-public properties via reflection when using a JDK < 1.4. Overcome the problem by making these properties public and document the reason in the code for future mortals! From: Russ Freeman <russ@freesoft.co.uk>
Can I disable the Session cache?
You can't disable it, because that would expose you to stack overflows where there are circular references, etc. You can, however, either clear() it, or change the FlushMode.
Issues with MS SQL Server UID (GUIDs)
MS SQL Server UID is a data type of 16-bytes binary values that operate as globally unique identifiers (GUIDs). In character string format the UID looks like this: '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}' I found that this data type could cause some problems when used in i.e. loading an object from the database. The following two examples will both have the same result:
session.load(MyObject.class, "{2C90AA1E-00F8-00F8-0001-FFFFF8F40C12}");
, and:
session.load(MyObject.class, "2C90AA1E-00F8-00F8-0001-FFFFF8F40C12");
MS SQL Server seems to remove the brackets from the UID when querying the database. When using this together with Apache JCS the difference between using brackets and not using brackets is crucial! Suppose that MyObject have a one-to-many relationship to MyOtherObject, and this relationship is bi-directional (MyOtherObject have a reference to its parent MyObject). When loading MyObject from database with an UID including brackets, Apache JCS will store this UID (with brackets) as the key used for locating the object in cache. This will cause the related object, MyOtherObject, not finding its parent (MyObject) in the cache and therefore load another instance of the parent MyObject into the cache. The reason for this is; MyOtherObject will have a reference to the parent defined as an foreign key in the database. When MyOtherObject will get loaded it will try to lookup its parent by an UID without brackets! Since we specified to load MyObject by an UID with brackets you wont get a hit in the cache cause MS SQL Server returns the UID from database without brackets. A new instance of MyObject will be created and its key in Apache JCS will be a UID without the brackets. Now we have two instances of the parent MyObject in Apache JCS, one located by its UID with brackets and another located by its UID without brackets. If you load MyObject by its UID with brackets, change the state of the object and then tries to persist the changes to database - it just wont happen! One UPDATE will be performed cause you have changed the state of the instance MyObject stored in Apache JCS located by its UID with brackets, another UPDATE on the related instance MyOtherObject will be performed, and another UPDATE on MyObject will be performed - on the other instance to MyObject handled by MyOtherObject. This instance have not been changed but is different from the instance of MyObject located by its UID with brackets and therefor be persisted into the database with its old values. And since MS SQL Server sees the UID with or without the brackets as same, the updated row in database with the new values will be overwriten with the old values! REMEBER! An UID with brackets or without brackets is handled the same by MS SQL Server, but NOT by Apache JCS. From Andreas Eriksson <andreas_developer@hotmail.com>
I want to use Java 1.2.x with hibernate. What are my options.
Recompile Hibernate with a modern J2SDK, eg, JDK 1.4.2 and compiler option target="1.1". In other words, just add target="1.1" attribute in the javac tag of "compile" task of the build.xml. When you run your program, you may find JIT errors. In this case, just disable JIT by specifying JVM option -Djava.compiler=NONE.
During startup there is an error: could not instantiate CacheProvider: net.sf.ehcache.hibernate.Provider
Since 2.1, ehcache is now the default hibernate cache provider. You have two options: * Add ehcache.jar to your classpath * Specify an alternative cache provider by setting the hibernate.cache.provider_class property - net.sf.hibernate.cache.HashtableCacheProvider should be okay if you dont use any caching.
Batch update row count wrong / SQL update or deletion failed (row not found)
Most common reason: This most likely means you are using a primitive type identifier (int, long) and have not set the unsaved-value mapping or have set it to a wrong value. Please take a look at Chapter 5.1.4 of the reference documentation. possible other causes? : (Possibly related, but it doesn't seem like it:) You may also get this error if you have parents and children arranged in a one-to-many relationship, and you try to update the parent before first saving the child. If you have parent and child tables like so:
create table parent ( id bigint not null primary key )
create table child ( id bigint not null primary key, name varchar(255), parent_id bigint )
and a hibernate mapping:
<hibernate-mapping>
<class name="eg.Parent" table="parent">
<id name="id">
<generator class="native"/>
</id>
<set name="children">
<key column="parent_id"/>
<one-to-many class="eg.Child"/>
</set>
</class>
</hibernate-mapping>
then something like:
Parent p = session.load(Parent.class, new Integer(1)); // parent already exists
Set s = p.getChildren();
Child c = new Child();
s.add(c);
//session.save(c);
session.save(p);
Will fail! You must save the child first (by uncommenting the commented-out line) even though--at the time of saving--it has no parent_id!
Collections and Interceptor.onFlushDirty/onDelete
Changes to persistent collections do not trigger onFlushDirty. Updating non-collection properties along with collections will trigger onFlushDirty, but updating collections alone won't. Also, persistent collections (other than arrays) get special treatment with respect to finding changes made since the last flush. Non-collection, dependant value properties are cached when they are loaded and changes are found (during a flush) by comparing the current state of the object to the cache. Collections (in the java.util.Collection sense) are not cached when they are loaded. Instead, Hibernate wraps the collection in a special Hibernate implementation (see chapter 6 of the Hibernate2 Reference Documentation). When you update the collection, Hibernate remembers the changes internally. This means that when onFlushDirty is called on your interceptor, the Object[] that is supposed to contain the previous state may not give you the previous state of modified collections. If you have updated the collection (as you are supposed to), rather than replacing it, the interceptor will see the same collection in prevousState as in currentState - it will not see the collection that was loaded from the database in previousState. onDelete is similar in that the interceptor will see any changes that have been made to the deleted object's state during the session. It will not see the original state from the database.
I am getting assertion failure saying "cannot access loading collection" in Hibernate 2.1.2, but it worked with Hibernate 2.1.1
You are probably having an inverse-mapped child object that adds itself to the parent collection when the setParent() method (or whatever the property setter is named) is called. This property setter is called by Hibernate during the loading of the object graph, and in 2.1.2 Hibernate no longer allows you to modify a collection that is still being loaded. My solution is to split the property setter in two: setParent() only sets the parent field, and another method "setParentFromApp()" sets the parent, and does the bookkeeping of the parent collection ("FromApp" suffix signifies this method is meant to be called from the application code to set the parent property, while the plain setParent() should be exclusively called by Hibernate from now on.
My tables are disappearing when I start my program or when my program ends (may also look like 'delete from <table> has been run)
Check the setting of 'hibernate.hbm2ddl.auto'. If it is set to 'create', hibernate will drop and recreate the tables. If it is set to 'create-drop', then the tables will be dropped when the program ends (if the SessionFactory is closed). Note that setting hibernate.show_sql=true will not cause the drop SQL to be shown.
|