From: <hib...@li...> - 2006-07-28 10:05:51
|
Author: ste...@jb... Date: 2006-07-26 13:16:46 -0400 (Wed, 26 Jul 2006) New Revision: 10171 Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/User.java Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/JoinTest.java branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/Person.hbm.xml Log: ported fix for HHH-1713 to 3.2 branch Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java =================================================================== --- branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-07-26 17:10:17 UTC (rev 10170) +++ branches/Branch_3_2/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2006-07-26 17:16:46 UTC (rev 10171) @@ -1961,6 +1961,7 @@ final boolean hasDeferred = rootPersister.hasSequentialSelect(); PreparedStatement sequentialSelect = null; ResultSet sequentialResultSet = null; + boolean sequentialSelectEmpty = false; try { if ( hasDeferred ) { @@ -1970,7 +1971,30 @@ sequentialSelect = session.getBatcher().prepareSelectStatement( sql ); rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session ); sequentialResultSet = sequentialSelect.executeQuery(); - sequentialResultSet.next(); + if ( !sequentialResultSet.next() ) { + // TODO: Deal with the "optional" attribute in the <join> mapping; + // this code assumes that optional defaults to "true" because it + // doesn't actually seem to work in the fetch="join" code + // + // Note that actual proper handling of optional-ality here is actually + // more involved than this patch assumes. Remember that we might have + // multiple <join/> mappings associated with a single entity. Really + // a couple of things need to happen to properly handle optional here: + // 1) First and foremost, when handling multiple <join/>s, we really + // should be using the entity root table as the driving table; + // another option here would be to choose some non-optional joined + // table to use as the driving table. In all likelihood, just using + // the root table is much simplier + // 2) Need to add the FK columns corresponding to each joined table + // to the generated select list; these would then be used when + // iterating the result set to determine whether all non-optional + // data is present + // My initial thoughts on the best way to deal with this would be + // to introduce a new SequentialSelect abstraction that actually gets + // generated in the persisters (ok, SingleTable...) and utilized here. + // It would encapsulated all this required optional-ality checking... + sequentialSelectEmpty = true; + } } } @@ -1988,11 +2012,14 @@ //decide which ResultSet to get the property value from: final boolean propertyIsDeferred = hasDeferred && rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] ); - final ResultSet propertyResultSet = propertyIsDeferred ? sequentialResultSet : rs; - final String[] cols = propertyIsDeferred ? - propertyColumnAliases[i] : suffixedPropertyColumns[i]; - - values[i] = types[i].hydrate( propertyResultSet, cols, session, object ); + if ( propertyIsDeferred && sequentialSelectEmpty ) { + values[i] = null; + } + else { + final ResultSet propertyResultSet = propertyIsDeferred ? sequentialResultSet : rs; + final String[] cols = propertyIsDeferred ? propertyColumnAliases[i] : suffixedPropertyColumns[i]; + values[i] = types[i].hydrate( propertyResultSet, cols, session, object ); + } } else { values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY; Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/JoinTest.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/JoinTest.java 2006-07-26 17:10:17 UTC (rev 10170) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/JoinTest.java 2006-07-26 17:16:46 UTC (rev 10171) @@ -90,6 +90,39 @@ s.close(); } + public void testSequentialSelectsOptionalData() throws Exception { + Session s = openSession(); + Transaction t = s.beginTransaction(); + + User jesus = new User(); + jesus.setName("Jesus Olvera y Martinez"); + jesus.setSex('M'); + + s.save(jesus); + + assertEquals( s.createQuery("from java.io.Serializable").list().size(), 0 ); + + assertEquals( s.createQuery("from Person").list().size(), 1 ); + assertEquals( s.createQuery("from Person p where p.class is null").list().size(), 0 ); + assertEquals( s.createQuery("from Person p where p.class = User").list().size(), 1 ); + assertTrue(s.createQuery("from User u").list().size()==1); + s.clear(); + + // Remove the optional row from the join table and requery the User obj + s.connection().prepareStatement("delete from t_user").execute(); + s.clear(); + + jesus = (User) s.get( Person.class, new Long( jesus.getId() ) ); + s.clear(); + + // Cleanup the test data + s.delete(jesus); + + assertTrue( s.createQuery("from Person").list().isEmpty() ); + t.commit(); + s.close(); + } + protected String[] getMappings() { return new String[] { "join/Person.hbm.xml" }; Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/Person.hbm.xml =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/Person.hbm.xml 2006-07-26 17:10:17 UTC (rev 10170) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/Person.hbm.xml 2006-07-26 17:16:46 UTC (rev 10171) @@ -23,53 +23,36 @@ --> -<hibernate-mapping - package="org.hibernate.test.join" - default-access="field"> - - <class name="Person" - table="person" - lazy="true" - discriminator-value="null"> - - <id name="id" - column="person_id" - unsaved-value="0"> +<hibernate-mapping package="org.hibernate.test.join" default-access="field"> + + <class name="Person" table="person" lazy="true" discriminator-value="null"> + + <id name="id" column="person_id" unsaved-value="0"> <generator class="native"/> </id> - - <discriminator column="person_type" - type="string" - length="1" - not-null="false" - force="true"/> <!--unnecessary, in case we had other unknown discriminator values --> - - <property name="name" - not-null="true" - length="80"/> - <property name="sex" - not-null="true" - update="false"/> - + + <!-- force is unnecessary, in case we had other unknown discriminator values --> + <discriminator column="person_type" type="string" length="1" not-null="false" force="true"/> + + <property name="name" not-null="true" length="80"/> + <property name="sex" not-null="true" update="false"/> + <join table="address"> <key column="address_id"/> <property name="address"/> <property name="zip"/> <property name="country"/> </join> - + <subclass name="Employee" lazy="true" discriminator-value="E"> <join table="employee" fetch="select"> <key column="person_id"/> - <property name="title" - not-null="true" - length="20"/> - <property name="salary" - length="0"/> + <property name="title" not-null="true" length="20"/> + <property name="salary" length="0"/> <many-to-one name="manager"/> </join> </subclass> - + <subclass name="Customer" lazy="true" discriminator-value="C"> <join table="customer" fetch="select"> <key column="person_id"/> @@ -77,8 +60,19 @@ <many-to-one name="salesperson"/> </join> </subclass> - + + <subclass name="User" lazy="true" discriminator-value="U"> + <join table="t_user" fetch="select" optional="true"> + <key column="person_id"/> + <property name="login" column="u_login"/> + </join> + <join table="t_silly" fetch="select" optional="true" > + <key column="person_id"/> + <property name="silly"/> + </join> + </subclass> + </class> - + </hibernate-mapping> Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/User.java =================================================================== --- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/User.java 2006-07-26 17:10:17 UTC (rev 10170) +++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/join/User.java 2006-07-26 17:16:46 UTC (rev 10171) @@ -0,0 +1,23 @@ +//$Id$ +package org.hibernate.test.join; + +/** + * @author Mike Dillon + */ +public class User extends Person { + private String login; + private String silly; + + /** + * @return Returns the login. + */ + public String getLogin() { + return login; + } + /** + * @param login The login to set. + */ + public void setLogin(String login) { + this.login = login; + } +} |