Hibernate version: 3.2.5.ga
I've managed to find some odd behaviour with one-to-one relationships. I'm hoping this is because I'm not handling the mappings properly, but I basically copied them directly from the documentation.
Here's my tables / objects / hbm files:
Code:
a(id INT AUTO_INCREMENT, bId INT NOT NULL, PRIMARY KEY(id))
b(id INT AUTO_INCREMENT, PRIMARY KEY(id))
class A {
private int id;
private B b;
// getters / setters ...
}
class B {
private int id;
private A a;
// getters / setters ...
}
<class name="A" table="a">
<id name="id" column="id" type="java.lang.Long">
<generator class="native">
<param name="sequence">global_seq</param>
</generator>
</id>
<many-to-one name="b" column="bId" not-null="true" unique="true" cascade="save-update" />
</class>
<class name="B" table="b">
<id name="id" column="id" type="java.lang.Long">
<generator class="native">
<param name="sequence">global_seq</param>
</generator>
</id>
<one-to-one name="a" class="A" constrained="true" property-ref="b" cascade="save-update" />
</class>
Now, when I get a list of A, my log file shows n+1 selects:
Code:
org.hibernate.SQL - select this_.id as id33_6_, this_.bId as a_33_6_, b_.id as id31_1_ from a this_ inner join b b_ on this_.bId=b_.id
org.hibernate.SQL - select a_.id as id33_0_, a_.bId as a2_33_0_ from a a_ where a_.bId=?
org.hibernate.SQL - select a_.id as id33_0_, a_.bId as a2_33_0_ from a a_ where a_.bId=?
org.hibernate.SQL - select a_.id as id33_0_, a_.bId as a2_33_0_ from a a_ where a_.bId=?
...
The hibernate log suggests that it needs to "initialize the entity" in those extra selects:
Code:
org.hibernate.loader.Loader - result set row: 0
org.hibernate.loader.Loader - result row: EntityKey[B#8117], EntityKey[A#18877]
org.hibernate.loader.Loader - result set row: 1
org.hibernate.loader.Loader - result row: EntityKey[B#8118], EntityKey[A#18878]
org.hibernate.loader.Loader - result set row: 2
org.hibernate.loader.Loader - result row: EntityKey[B#8119], EntityKey[A#18879]
...
org.hibernate.engine.TwoPhaseLoad - resolving associations for [B#8117]
org.hibernate.loader.Loader - loading entity: [A#8117]
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - result set row: 0
org.hibernate.loader.Loader - result row: EntityKey[A#18877]
org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
org.hibernate.loader.Loader - done entity load
org.hibernate.engine.TwoPhaseLoad - done materializing entity [B#8117]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [A#18877]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [A#18877]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [B#8118]
org.hibernate.loader.Loader - loading entity: [A#8118]
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - result set row: 0
org.hibernate.loader.Loader - result row: EntityKey[A#18878]
org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
org.hibernate.loader.Loader - done entity load
org.hibernate.engine.TwoPhaseLoad - done materializing entity [B#8118]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [A#18878]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [A#18878]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [B#8119]
org.hibernate.loader.Loader - loading entity: [A#8119]
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - result set row: 0
org.hibernate.loader.Loader - result row: EntityKey[A#18879]
org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
org.hibernate.loader.Loader - done entity load
org.hibernate.engine.TwoPhaseLoad - done materializing entity [B#8119]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [A#18879]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [A#18879]
...
Any reason why hibernate thinks it must select again for object a, when it could get that information from the original query? I've found that if I add a fetch="join" to the many-to-one relationship, it just performs this select:
Code:
select ... from a inner join b left outer join a
Ideally, I would like to remove any re-querying or joining of table a. Thanks for your help!