Hibernate Users FAQ - Common Problems
- Common Problems
- I saved / deleted / updated an object / collection but I can't see the changes in the database!
- I saved a parent object but its associated objects weren't saved to the database.
- I'm using a one-to-many association with a NOT NULL constraint on the key column and Hibernate causes constraint violations.
- I'm having trouble with a bidirectional association.
- I'm still having trouble!
- Can't I have a bidirectional association using a List?
- I get a log message: Parsing XML: unknown system id
- I get: reflection optimizer disabled
- I'm using assigned identifiers, or a <composite-id> with cascades or saveOrUpdate() and Hibernate throws a StaleObjectState exception or SQL insert, update or delete failed (row not found).
- Hibernate keeps deleting and recreating my collection!
- Hibernate throws a PropertyAccessException or NullPointerException when I load or query an object!
- I removed an object from a collection mapped with cascade="all" but the object was not deleted!
- Hibernate updates an object in the database, when I didn't change anything!
- I'm confused about the semantics of saveOrUpdate().
- saveOrUpdate(), or cascade, just creates new rows for old instances (or causes a unique key violation)!
- saveOrUpdate(), or cascade, tries to update nonexistent rows for new instances!
- How does inverse="true" affect the semantics of cascade="all"?
- I'm using a composite identifier and Hibernate causes a stack overflow!
- I get a ClassCastException when using a composite identifier
- I get a ClassCastException when I specify a collection sort attribute.
- I have some other kind of wierd bugs.....
- I'm using Hibernate in a CMT session bean or BMP entity bean and I recieve an exception whenever I try to commit() the Transaction or JDBC Connection.
- How do I use Hibernate with CMT?
- How do a write a query that returns objects based upon a WHERE clause condition applied to their collection elements?
- I want to retrieve query results, one page at a time
- I see a java.lang.AbstractMethodError: net/sf/hibernate/persister/AbstractEntityPersister.... at startup!
- I am getting a PropertyAccessException, and the error trace suggests to turn off the reflection optimizer. Howerver, it doesn't seem that I can set this in hibernate.cfg.xml.
- I have a property named like getAFoo() / setAFoo() and Hibernate throws a PropertyNotFoundException at startup.
- Hibernate tries to connect to http://hibernate.sourceforge.net at startup!
- What is the lifecycle of a Hibernate Session?
Common Problems
I saved / deleted / updated an object / collection but I can't see the changes in the database!Hibernate will not execute any SQL until you either call Transaction.commit() (if using the Transaction API) or Session.flush() (if you are not) at the end of a session to flush your in-memory changes to the database. If you are not using the Transaction API, you must then explicitly commit the transaction (by committing the JTA transaction or JDBC Connection).
I saved a parent object but its associated objects weren't saved to the database.Associated objects must be saved explicitly (by calling Session.save()) or the association must be mapped with cascade="all" or cascade="save-update".
I'm using a one-to-many association with a NOT NULL constraint on the key column and Hibernate causes constraint violations.Use a bidirectional association, mapping the many-valued end with inverse="true".
I'm having trouble with a bidirectional association.When you update a bidirectional association you must update both ends.
parent.getChildren().add(child);
child.setParent(parent);
I'm still having trouble!Read the documentation! There's a detailed chapter about "Parent/Child Relationships" in the reference documentation including code examples.
Can't I have a bidirectional association using a List?
<hibernate-mapping>
<class name="eg.Parent">
<id name="id">
<generator class="sequence"/>
</id>
<list name="children" lazy="true">
<key column="parent_id"/>
<index column="child_order"/>
<one-to-many class="eg.Child"/>
</list>
</class>
<class name="eg.Child">
<id name="id">
<generator class="sequence"/>
</id>
<property name="name"/>
<property name="childOrder" column="child_order" type="int" update="false" not-null="true"/>
<many-to-one name="parent" class="eg.Parent" column="parent_id" not-null="true"/>
</class>
</hibernate-mapping>
Notice how the inverse was removed from the Parent collection (now a List). This is because if the List is to be ordered and managed by Hibernate, you need to work directly with that List for the changes to the order to be computed. As an example, if you had a Child object and you set it's Parent to null, the List in the Parent has to be updated as well, so the ordering can be redone. The short version of all of this is that if you have ordered Lists you want to change, you must change the List directly at some point via a Parent.getChildren().remove(child) or Parent.getChildren().add(child), etc.
I get a log message: Parsing XML: unknown system idIgnore it. Its quite normal when loading a mapping document as a resource.
I get: reflection optimizer disabledThats quite okay. For some classes we can't use CGLIB for property access, so we have to fall back to reflection. This will have a very minor effect upon performance. (CGLIB's MetaClass can't access final properties or nonpublic properties.)
I'm using assigned identifiers, or a <composite-id> with cascades or saveOrUpdate() and Hibernate throws a StaleObjectState exception or SQL insert, update or delete failed (row not found).Assigned identifiers, including composite identifiers, can't be used to distinguish newly instantiated instances from instances saved or loaded in a previous session. You will need to be more explicit; tell Hibernate exactly what you mean by calling either save() or update(). Or, in Hibernate2, use Interceptor.isUnsaved() to distinguish new from old instances. In Hibernate 2.1, the best solution is to set unsaved-value for the <version> or <timestamp> element, if your data is versioned.
Hibernate keeps deleting and recreating my collection!Unlike other Hibernate value types, Hibernate tracks actual collection instances using Java identity, ==. Your getter method should return the same collection instance as was assigned by Hibernate to the setter method (unless you don't mind the collection being removed and recreated every time the session is flushed). This doesn't mean you shouldn't return a different collection if you really are replacing the current collection with a new collection with completely different elements. In certain cases, this behaviour can even be taken advantage of to increase performance.
Hibernate throws a PropertyAccessException or NullPointerException when I load or query an object!A PropertyAccessException often occurs when the object being passed to the setter method is of the wrong type. Check your type mappings for the offending property. (To see exactly which property was the problem, you might need to disable the CGLIB reflection optimizer.) However, the most common cause of this problem is that Hibernate attempted to assign null to a property of primitive type. If your object has a primitive-type property mapped to a nullable database column then you will need to use a Hibernate custom type to assign a sensible default (primitive) value for the case of a null column value. A better solution is usually to use a wrapper type for the Java property.
I removed an object from a collection mapped with cascade="all" but the object was not deleted!cascade="all" cascades the delete() operation from parent to child. If this is a one-to-many association, try using cascade="all-delete-orphan". Another solution is to model your objects as value types rather than entities. (Value types are always persisted or removed along with their parent entity.) So you would use a <composite-element> mapping for the element class instead of modelling it as a seperate entity.
Hibernate updates an object in the database, when I didn't change anything!This always occurs because you actually did change something! Enable Hibernate's logging to debug level and search for is dirty in the log. That will tell you exactly what property is detected to be dirty.
I'm confused about the semantics of saveOrUpdate().Firstly, so long as you are not trying to use instances from one session in another new session, you should not need to use update() or saveOrUpdate(). Some whole applications will never use either of these methods. Usually update() or saveOrUpdate() are used in the following scenario:
- the application loads an object in the first session
- the object is passed up to the UI tier
- some modifications are made to the object
- the object is passed back down to the business logic tier
- the application persists these modifications by calling update() in a second session
saveOrUpdate() does the following:
- if the object is already persistent in this session, do nothing
- if the object has no identifier property, save() it
- if the object's identifier matches the criteria specified by unsaved-value, save() it
- if another object associated with the session has the same identifier, throw an exception
- otherwise, update() it
saveOrUpdate(), or cascade, just creates new rows for old instances (or causes a unique key violation)!There are two reasons why this could occur:
- The <id> element does not specify the correct unsaved-value
- You are using an assigned identifier (or a composite identifier)
In the first case, you should simply specify unsaved-value. In the second case, you can't use saveOrUpdate(). You should explicitly call save() or update() on a case-by-case basis, use Interceptor.isUnsaved in Hibernate2, or use version unsavec-value in Hibernate 2.1.
saveOrUpdate(), or cascade, tries to update nonexistent rows for new instances!Again, specify unsaved-value correctly.
How does inverse="true" affect the semantics of cascade="all"? It doesn't.
I'm using a composite identifier and Hibernate causes a stack overflow!You must override equals() and hashCode() correctly on your composite identifier class. This is quite critical.
I get a ClassCastException when using a composite identifierDoes the composite identifier class implement Serializable?
I get a ClassCastException when I specify a collection sort attribute.When you first instantiate a sorted collection, it must be an instance of SortedSet, or SortedMap. Use a TreeSet or HashMap, for example.
I have some other kind of wierd bugs.....Carefully check the accessor methods for your persistent properties. Broken get/set pairs are a common source of bugs. Remember Hibernate might call a getter method multiple times during a session. Also, make sure that a call to an accessor method couldn't do anything wierd ... like initialize a lazy collection or proxy. For some classes it can be worthwhile to provide two get/set pairs for certain properties - one pair for business code and one for Hibernate.
I'm using Hibernate in a CMT session bean or BMP entity bean and I recieve an exception whenever I try to commit() the Transaction or JDBC Connection.In a CMT environment, you must let the container take responsibility for transaction management. Application code must still perform all the usual Session management, ie. Session.flush(), Session.close().
How do I use Hibernate with CMT?Just do it. CMT means neither Hibernate nor user code needs to worry about starting / stopping transactions.
How do a write a query that returns objects based upon a WHERE clause condition applied to their collection elements?There are two possibilities:
select distinct parent
from Parent parent
join parent.children child
where child.name = :name
from Parent parent where :childId in elements(parent.children)
The first query uses a table join; the second uses a subquery. The first query allows constraints to be applied to element properties; the second does not. You may not need the distinct keyword in the first query.
I want to retrieve query results, one page at a timeUse Query.setMaxResults() and Query.setFirstResult() for query paging.
I see a java.lang.AbstractMethodError: net/sf/hibernate/persister/AbstractEntityPersister.... at startup!(Michael Davidovich) The problem is the -classic JVM debug option, which is present in both Jboss and IntelliJ project options, beware! (Christian Bauer) Recompiling Hibernate with your JDK is the other solution.
I am getting a PropertyAccessException, and the error trace suggests to turn off the reflection optimizer. Howerver, it doesn't seem that I can set this in hibernate.cfg.xml.Unfortunately, there are two properties which may only be set at the "system" level, ie. in hibernate.properties. This is one of them.
I have a property named like getAFoo() / setAFoo() and Hibernate throws a PropertyNotFoundException at startup.Use name="AFoo" from the property name, as per the JavaBeans spec.
This means that your XML parser does not support the EntityResolver callback that Hibernate uses to resolve the mapping DTD from inside hibernate2.jar. Either use a different XML parser, such as a recent version of Xerces, or edit your mapping documents to use a SYSTEM id instead of the PUBLIC id that we recommend in the documentation.
What is the lifecycle of a Hibernate Session?Almost all Hibernate applications use a new session for each database transaction. In a system which uses optimistic locking, it is acceptable to use a session per application transaction. An application transaction is a unit of work from the point of view of the user, which may actually span several requests and/or database transactions. The Hibernate session is nothing to do with a user login session! More advanced problems....
|