-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Collection loaded with sql-query throws NullPointerException
PostPosted: Thu May 01, 2008 11:38 am 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
Hello. I'm a long-time Hibernate user, lurker on the forums, and first-time poster. I have been chasing this problem for a week, on Windows, LINUX, and Solaris, using HSQLDB, MySQL, Postgres, and Oracle, in Eclipse, NetBeans, using Ant, and by command-line Java. All of the results are the same; I'm fairly certain that I've either missed some head-slapping keyword, or there's something wrong with the way I'm trying to do this.

I'm having a problem loading a collection in a related table using a sql-query. In the real version, the query is an Oracle CONNECT BY, but the test case provided herein fails with identical errors, and the query is simple and cross-database, and meets the basic need (first-level pass) that CONNECT BY provides.

Fundamentally, one class/table (Container, in the example) has a value (realtionshipId/RELATIONSHIP_ID) that is a key to another (Relationship) that contains a value that is not the primary key/identifier (owner). The basic idea is that the Container will have zero or more Relationship items based on the class values Container.relationshipId=Relationship.owner (database values Container.RELATIONSHIP_ID=Relationship.OWNER). In the Oracle CONNECT BY, this collection is an aggregate of the parent/children in in the Relationship table, but for this example, every Container has two related Relationship entries.

The rest of this is filled in from the "new topic" suggestion.

Hibernate version:

Tested with 3.2.6, but needs to work in 3.2.1 as well as that is the version approved for use on the real problem.

For this test, I simply added the hibernate3.jar and the minimum required to allow it to run and compile, pulled straight from the hibernate zip lib directory:

asm.jar cglib-2.1.3.jar commons-collections-2.1.1.jar commons-logging-1.0.4.jar dom4j-1.6.1.jar jta.jar

Additionally, the database is right from the hsqldb.jar from that download.

Mapping documents:

Currently the collection is settled as just a bag, but I have tried to use set as well; I've toyed with map and list, but for the easy-to-reproduce test, there's more configuration than I wanted to put. Additionally, the bag is filled with elements, but I've also tried one-to-many and many-to-many, and the results are the same. These elements are in the mapping, commented out, with their attributes shown. Obviously, if this is changed, the other must be removed, or if the collection type is changed, the end tag must be corrected. Additionally, these have been tested lazy and not lazy, again, with the same results.

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping default-lazy="false">
   <class name="Container" table="CONTAINER" mutable="false">
      <id name="id" type="integer">
         <column name="ID" />
      </id>

      <property name="data" column="DATA" type="string" />
      <property name="relationshipId" column="RELATIONSHIP_ID"
         type="integer" />

      <!-- ALSO TRIED -->
      <!-- set name="relationships" -->
      <bag name="relationships">
         <key property-ref="relationshipId" />
         <!-- ALSO TRIED -->
         <!-- many-to-many class="Relationship" / -->
         <!-- one-to-many class="Relationship" / -->
         <element type="Relationship" />
         <loader query-ref="loadRelationships" />
      </bag>
   </class>

   <class name="Relationship" table="RELATIONSHIP" mutable="false">
      <id name="id" type="integer">
         <column name="ID" />
      </id>

      <property name="owner" column="OWNER" type="integer" />
      <property name="rank" column="RANK" type="integer" />
   </class>

   <!-- LOAD RELATIONSHIPS BASED ON OWNER NOT ID -->
   <sql-query name="loadRelationships">
      <return alias="r" class="Relationship" />
      SELECT ID {r.id}, OWNER {r.owner}, RANK {r.rank} FROM
      RELATIONSHIP {r} WHERE OWNER=?
   </sql-query>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

Here's the whole test case.

The HSQLDB is created and destroyed with the test. The tables are created and filled with Session.createSQLQuery() to simulate the real condition of the data already existing. The session is flushed, and the objects are received and populated with simple Session.get().

Just before the failure occurs, the expected collection is gathered out of the Container object by use of Session.getNamedQuery(), and that does not fail. This leads me to be certain it is not the query or the query configuration in the hbm.xml file.

The failure occurs in the test when the collection in the Container is attempted to iterate. There is a comment in the test method that warns where the exception will occur.

Code:
import java.util.List;

import junit.framework.TestCase;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ContainerTest extends TestCase {
   private static SessionFactory factory = null;

   private Session session = null;

   public ContainerTest() {
      if (factory == null) {
         final Configuration configuration = new Configuration();

         configuration.setProperty("hibernate.dialect",
               "org.hibernate.dialect.HSQLDialect").setProperty(
               "hibernate.connection.driver_class",
               "org.hsqldb.jdbcDriver").setProperty(
               "hibernate.connection.url", "jdbc:hsqldb:mem:swbyjeff")
               .setProperty("hibernate.connection.username", "sa")
               .setProperty("hibernate.connection.password", "")
               .setProperty("hibernate.connection.pool_size", "1")
               .setProperty("hibernate.cache.provider_class",
                     "org.hibernate.cache.HashtableCacheProvider")
               .setProperty("hibernate.show_sql", "true");

         // Must create the tables before introducing ORM mappings
         final Session session = configuration.buildSessionFactory()
               .openSession();
         session.createSQLQuery(
               "CREATE TABLE CONTAINER ( id integer identity,"
                     + " data varchar(10), relationship_id integer )")
               .executeUpdate();
         session.createSQLQuery(
               "CREATE TABLE RELATIONSHIP ( id integer identity,"
                     + " owner integer, rank integer )").executeUpdate();

         // Now safe to tell configuration about ORM mappings
         configuration.addResource("Container.hbm.xml");

         // Rebuild the SessionFactory with additional configuration item
         factory = configuration.buildSessionFactory();
      }
   }

   @SuppressWarnings("unchecked")
   public void testContainerLoad() throws Exception {
      try {
         for (int i = 0; i < 10; i++) {
            final Integer id = Integer.valueOf(i);
            System.out.println("Getting container " + id);
            final Object object = getSession().get(Container.class, id);

            assertTrue("Not Container: " + object,
                  object instanceof Container);

            final Container container = (Container) object;
            System.out.println("Container " + container);
            assertEquals(id, container.getId());

            assertEquals("Number " + id, container.getData());
            assertNotNull(container.getRelationshipId());
            assertNotNull(container.getRelationships());

            // Using named query directly will succeed
            final List list = getSession().getNamedQuery(
                  "loadRelationships").setInteger(0,
                  container.getRelationshipId()).list();
            assertNotNull(list);
            assertFalse(list.isEmpty());
            System.out.println("Should have relationships " + list);

            boolean found = false;
            // Getting this iterator will throw NPE
            for (final Object containerRelationship : container
                  .getRelationships()) {
               assertTrue(containerRelationship instanceof Relationship);
               final Relationship relationship = (Relationship) containerRelationship;
               System.out.println(" Got " + relationship);
               assertEquals(container.getRelationshipId(), relationship
                     .getOwner());
               assertTrue("Not expecting " + relationship, list
                     .contains(relationship));
               list.remove(relationship);
               found = true;
            }
            assertTrue("Could not find any relationship", found);
            assertTrue("Container didn't get all relationships! " + list,
                  list.isEmpty());
         }
         assertNull(getSession().get(Container.class, Integer.valueOf(10)));
      } catch (Exception e) {
         e.printStackTrace();
         throw e;
      }
   }

   @Override
   protected void setUp() throws Exception {
      getSession().beginTransaction();

      // Add data
      int id = 11;
      for (int owner = 0; owner < 10; owner++) {
         assertEquals(1, getSession().createSQLQuery(
               "INSERT INTO CONTAINER "
                     + "(ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)")
               .setInteger(0, Integer.valueOf(owner)).setString(1,
                     "Number " + owner).setInteger(2,
                     Integer.valueOf(owner)).executeUpdate());
         for (int rank = 1; rank < 3; rank++) {
            assertEquals(1, getSession().createSQLQuery(
                  "INSERT INTO RELATIONSHIP "
                        + "(ID, OWNER, RANK) VALUES (?, ?, ?)")
                  .setInteger(0, Integer.valueOf(id++)).setInteger(1,
                        Integer.valueOf(owner)).setInteger(2,
                        Integer.valueOf(rank)).executeUpdate());
         }
      }

      getSession().flush();
   }

   @Override
   protected void tearDown() throws Exception {
      if (session != null) {
         session.getTransaction().rollback();
         session.close();
      }
      session = null;
   }

   private synchronized Session getSession() {
      if (session == null) {
         session = factory.openSession();
      }
      return session;
   }

}


The objects are trivial (getters/setters cut for brevity). Each contains an id, a trivial piece of data (data or rank), and the relating members (relationshipId -> owner). Each has equals/hashcode and a simple toString()

Code:
public class Container implements Serializable {

   private static final long serialVersionUID = -762978251577933701L;

   private String data = null;

   private Integer id = null;

   private Integer relationshipId = null;

   @SuppressWarnings("unchecked")
   private Collection relationships = null;

   @Override
   public boolean equals(final Object object) {
      return (object instanceof Container)
            && ((id == null) ? ((Container) object).id == null : id.equals(((Container) object).id));
   }

   @Override
   public int hashCode() {
      return Long.valueOf(serialVersionUID + ((id == null) ? 0 : id.hashCode())).hashCode();
   }

   @Override
   public String toString() {
      return this.getClass().getSimpleName() + "{id:" + id + ",data:" + data + ",relationshipId:" + relationshipId
            + "}";
   }
}

public class Relationship implements Serializable {

   private static final long serialVersionUID = -6275441596378037221L;

   private Integer id = null;

   private Integer owner = null;

   private Integer rank = null;

   @Override
   public boolean equals(final Object object) {
      return (object instanceof Relationship)
            && ((id == null) ? (((Relationship) object).id == null) : id.equals(((Relationship) object).id));
   }

   @Override
   public int hashCode() {
      return Long.valueOf(serialVersionUID + ((id == null) ? 0 : id.hashCode())).hashCode();
   }

   @Override
   public String toString() {
      return getClass().getSimpleName() + "{id:" + id + ",owner:" + owner + ",rank:" + rank + "}";
   }
}



Full stack trace of any exception that occurs:

Name and version of the database you are using:

For this test, using HSQLDB v1.8.0, but in production Oracle 10G

The generated SQL (show_sql=true):

This bit is taken right from the logs (included below). The "Getting" and "Container" and "Should have relationships" comments will help align with where the code is executing.

Code:
Getting container 0
Hibernate: select container0_.ID as ID0_0_, container0_.DATA as DATA0_0_, container0_.RELATIONSHIP_ID as RELATION3_0_0_ from CONTAINER container0_ where container0_.ID=?
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Container Container{id:0,data:Number 0,relationshipId:0}
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Should have relationships [Relationship{id:11,owner:0,rank:1}, Relationship{id:12,owner:0,rank:2}]
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?


Debug level Hibernate log excerpt:

Although I did build a log4j.properties and log4j.xml file, I could not get the basic configuration I have to give me debug output.

The core exception, the one that stops JUnit, is this:

Code:
java.lang.NullPointerException
   at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:164)
   at com.swbyjeff.ContainerTest.testContainerLoad(ContainerTest.java:85)


Here is the entire output from the run of the test program. Note the debug shows the package, while my "excerpts" above do not (brevity again). Occasionally the output differs as the System.err output may appear above some of the System.out output, but the indicated location (line 85) is always the same. Line 85 is the for() iterator on the Container.relationships collection.

Code:
May 1, 2008 10:03:52 AM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.2.6
May 1, 2008 10:03:52 AM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
May 1, 2008 10:03:52 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : cglib
May 1, 2008 10:03:52 AM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
May 1, 2008 10:03:52 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
May 1, 2008 10:03:52 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 1
May 1, 2008 10:03:52 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
May 1, 2008 10:03:52 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:mem:swbyjeff
May 1, 2008 10:03:52 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=sa, password=****}
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: HSQL Database Engine, version: 1.8.0
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: HSQL Database Engine Driver, version: 1.8.0
May 1, 2008 10:03:53 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.HSQLDialect
May 1, 2008 10:03:53 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
May 1, 2008 10:03:53 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: auto
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL inserts for batching: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
May 1, 2008 10:03:53 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.HashtableCacheProvider
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Named query checking : enabled
May 1, 2008 10:03:53 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
May 1, 2008 10:03:53 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
May 1, 2008 10:03:53 AM org.hibernate.cfg.Configuration addResource
INFO: Reading mappings from resource : com/swbyjeff/orm/Container.hbm.xml
May 1, 2008 10:03:53 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: com.swbyjeff.Container -> CONTAINER
May 1, 2008 10:03:53 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: com.swbyjeff.Container.relationships -> relationships
May 1, 2008 10:03:53 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: com.swbyjeff.Relationship -> RELATIONSHIP
May 1, 2008 10:03:53 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
May 1, 2008 10:03:53 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 1
May 1, 2008 10:03:53 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
May 1, 2008 10:03:53 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:mem:swbyjeff
May 1, 2008 10:03:53 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=sa, password=****}
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: HSQL Database Engine, version: 1.8.0
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: HSQL Database Engine Driver, version: 1.8.0
May 1, 2008 10:03:53 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.HSQLDialect
May 1, 2008 10:03:53 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
May 1, 2008 10:03:53 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: auto
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL inserts for batching: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
May 1, 2008 10:03:53 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.HashtableCacheProvider
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
May 1, 2008 10:03:53 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Named query checking : enabled
May 1, 2008 10:03:53 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
May 1, 2008 10:03:54 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Hibernate: CREATE TABLE CONTAINER ( id integer identity, data varchar(10), relationship_id integer )
Hibernate: CREATE TABLE RELATIONSHIP ( id integer identity, owner integer, rank integer )
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO CONTAINER (ID, DATA, RELATIONSHIP_ID) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Hibernate: INSERT INTO RELATIONSHIP (ID, OWNER, RANK) VALUES (?, ?, ?)
Getting container0
Hibernate: select container0_.ID as ID0_0_, container0_.DATA as DATA0_0_, container0_.RELATIONSHIP_ID as RELATION3_0_0_ from CONTAINER container0_ where container0_.ID=?
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Container Container{id:0,data:Number 0,relationshipId:0}
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Should have relationships [Relationship{id:11,owner:0,rank:1}, Relationship{id:12,owner:0,rank:2}]
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
java.lang.NullPointerException
   at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:250)
   at com.swbyjeff.ContainerTest.testContainerLoad(ContainerTest.java:85)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:164)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:120)
   at junit.framework.TestSuite.runTest(TestSuite.java:230)
   at junit.framework.TestSuite.run(TestSuite.java:225)
   at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 01, 2008 11:47 am 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
I see immediately that I put the exception out of order...I hope that doesn't ruffle any feathers. <wink/>


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 01, 2008 5:48 pm 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
Someone pointed out that I hadn't added the log4j JAR to the project. Doing that allowed me to get the Hibernate debug output. It's too much for this post, but here's the bits at and after the test starts loading the first Container in the test (line 68-ish):

Code:
Getting container 0
org.hibernate.event.def.DefaultLoadEventListener - loading entity: [com.swbyjeff.Container#0]
org.hibernate.event.def.DefaultLoadEventListener - attempting to resolve: [com.swbyjeff.Container#0]
org.hibernate.event.def.DefaultLoadEventListener - object not resolved in any cache: [com.swbyjeff.Container#0]
org.hibernate.persister.entity.AbstractEntityPersister - Fetching entity: [com.swbyjeff.Container#0]
org.hibernate.loader.Loader - loading entity: [com.swbyjeff.Container#0]
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.SQL - select container0_.ID as ID0_0_, container0_.DATA as DATA0_0_, container0_.RELATIONSHIP_ID as RELATION3_0_0_ from CONTAINER container0_ where container0_.ID=?
Hibernate: select container0_.ID as ID0_0_, container0_.DATA as DATA0_0_, container0_.RELATIONSHIP_ID as RELATION3_0_0_ from CONTAINER container0_ where container0_.ID=?
org.hibernate.jdbc.AbstractBatcher - preparing statement
org.hibernate.type.IntegerType - binding '0' to parameter: 1
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - processing result set
org.hibernate.loader.Loader - result set row: 0
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Container#0]
org.hibernate.loader.Loader - Initializing object from ResultSet: [com.swbyjeff.Container#0]
org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [com.swbyjeff.Container#0]
org.hibernate.type.StringType - returning 'Number 0' as column: DATA0_0_
org.hibernate.type.IntegerType - returning '0' as column: RELATION3_0_0_
org.hibernate.loader.Loader - done processing result set (1 rows)
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.jdbc.AbstractBatcher - closing statement
org.hibernate.loader.Loader - total objects hydrated: 1
org.hibernate.engine.TwoPhaseLoad - resolving associations for [com.swbyjeff.Container#0]
org.hibernate.engine.loading.LoadContexts - creating collection wrapper:[com.swbyjeff.Container.relationships#0]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [com.swbyjeff.Container#0]
org.hibernate.engine.StatefulPersistenceContext - initializing non-lazy collections
org.hibernate.event.def.DefaultInitializeCollectionEventListener - initializing collection [com.swbyjeff.Container.relationships#0]
org.hibernate.event.def.DefaultInitializeCollectionEventListener - checking second-level cache
org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection not cached
org.hibernate.persister.collection.NamedQueryCollectionInitializer - initializing collection: com.swbyjeff.Container.relationships using named query: loadRelationships
org.hibernate.impl.SessionImpl - setting flush mode to: MANUAL
org.hibernate.engine.query.QueryPlanCache - located native-sql query plan in cache (SELECT ID {r.id}, OWNER {r.owner}, RANK {r.rank} FROM
      RELATIONSHIP {r} WHERE OWNER=?)
org.hibernate.impl.SessionImpl - SQL query: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.SQL - SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - preparing statement
org.hibernate.type.IntegerType - binding '0' to parameter: 1
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - processing result set
org.hibernate.loader.Loader - result set row: 0
org.hibernate.type.IntegerType - returning '11' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#11]
org.hibernate.loader.Loader - Initializing object from ResultSet: [com.swbyjeff.Relationship#11]
org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [com.swbyjeff.Relationship#11]
org.hibernate.type.IntegerType - returning '0' as column: OWNER2_0_
org.hibernate.type.IntegerType - returning '1' as column: RANK2_0_
org.hibernate.loader.Loader - result set row: 1
org.hibernate.type.IntegerType - returning '12' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#12]
org.hibernate.loader.Loader - Initializing object from ResultSet: [com.swbyjeff.Relationship#12]
org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [com.swbyjeff.Relationship#12]
org.hibernate.type.IntegerType - returning '0' as column: OWNER2_0_
org.hibernate.type.IntegerType - returning '2' as column: RANK2_0_
org.hibernate.loader.Loader - done processing result set (2 rows)
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.jdbc.AbstractBatcher - closing statement
org.hibernate.loader.Loader - total objects hydrated: 2
org.hibernate.engine.TwoPhaseLoad - resolving associations for [com.swbyjeff.Relationship#11]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [com.swbyjeff.Relationship#11]
org.hibernate.engine.TwoPhaseLoad - resolving associations for [com.swbyjeff.Relationship#12]
org.hibernate.engine.TwoPhaseLoad - done materializing entity [com.swbyjeff.Relationship#12]
org.hibernate.impl.SessionImpl - setting flush mode to: AUTO
org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection initialized
org.hibernate.loader.Loader - done entity load
Container Container{id:0,data:Number 0,relationshipId:0}
org.hibernate.engine.query.QueryPlanCache - located native-sql query plan in cache (SELECT ID {r.id}, OWNER {r.owner}, RANK {r.rank} FROM
      RELATIONSHIP {r} WHERE OWNER=?)
org.hibernate.impl.SessionImpl - SQL query: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.SQL - SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - preparing statement
org.hibernate.type.IntegerType - binding '0' to parameter: 1
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - processing result set
org.hibernate.loader.Loader - result set row: 0
org.hibernate.type.IntegerType - returning '11' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#11]
org.hibernate.loader.Loader - result set row: 1
org.hibernate.type.IntegerType - returning '12' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#12]
org.hibernate.loader.Loader - done processing result set (2 rows)
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.jdbc.AbstractBatcher - closing statement
org.hibernate.loader.Loader - total objects hydrated: 0
org.hibernate.engine.StatefulPersistenceContext - initializing non-lazy collections
Should have relationships [Relationship{relationship:11,owner:0,rank:1}, Relationship{relationship:12,owner:0,rank:2}]
org.hibernate.event.def.DefaultInitializeCollectionEventListener - initializing collection [com.swbyjeff.Container.relationships#0]
org.hibernate.event.def.DefaultInitializeCollectionEventListener - checking second-level cache
org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection not cached
org.hibernate.persister.collection.NamedQueryCollectionInitializer - initializing collection: com.swbyjeff.Container.relationships using named query: loadRelationships
org.hibernate.impl.SessionImpl - setting flush mode to: MANUAL
org.hibernate.engine.query.QueryPlanCache - located native-sql query plan in cache (SELECT ID {r.id}, OWNER {r.owner}, RANK {r.rank} FROM
      RELATIONSHIP {r} WHERE OWNER=?)
org.hibernate.impl.SessionImpl - SQL query: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
org.hibernate.SQL - SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
Hibernate: SELECT ID ID2_0_, OWNER OWNER2_0_, RANK RANK2_0_ FROM
      RELATIONSHIP r WHERE OWNER=?
org.hibernate.jdbc.AbstractBatcher - preparing statement
org.hibernate.type.IntegerType - binding '0' to parameter: 1
org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
org.hibernate.loader.Loader - processing result set
org.hibernate.loader.Loader - result set row: 0
org.hibernate.type.IntegerType - returning '11' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#11]
org.hibernate.loader.Loader - result set row: 1
org.hibernate.type.IntegerType - returning '12' as column: ID2_0_
org.hibernate.loader.Loader - result row: EntityKey[com.swbyjeff.Relationship#12]
org.hibernate.loader.Loader - done processing result set (2 rows)
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.jdbc.AbstractBatcher - closing statement
org.hibernate.loader.Loader - total objects hydrated: 0
org.hibernate.engine.StatefulPersistenceContext - initializing non-lazy collections
org.hibernate.impl.SessionImpl - setting flush mode to: AUTO
org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection initialized
java.lang.NullPointerException
   at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:250)
   at com.swbyjeff.ContainerTest.testContainerLoad(ContainerTest.java:84)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:164)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:120)
   at junit.framework.TestSuite.runTest(TestSuite.java:230)
   at junit.framework.TestSuite.run(TestSuite.java:225)
   at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
org.hibernate.transaction.JDBCTransaction - rollback
org.hibernate.transaction.JDBCTransaction - rolled back JDBC Connection
org.hibernate.jdbc.JDBCContext - after transaction completion
org.hibernate.jdbc.ConnectionManager - aggressively releasing JDBC connection
org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
org.hibernate.connection.DriverManagerConnectionProvider - returning connection to pool, pool size: 1
org.hibernate.impl.SessionImpl - after transaction completion
org.hibernate.impl.SessionImpl - closing session
org.hibernate.jdbc.ConnectionManager - connection already null in cleanup : no action


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 02, 2008 12:23 pm 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
I know the "how to post" says to not keep adding to your own post, but I'm also trying to "continue to solve the problem," and as much as I seek the assistance, it may be the case that someone else with the problem will see this chain and maybe help find the solution.

I'm debugging the Hibernate loading of my collection, the snippet reproduced here for those that don't read long posts; the whole thing is above. In my <class> I have a type (Container) that contains relationships, which should be being loaded as a set using the sql-query loadRelationships. This way, Container has Relationships that are related not by the main id of the classes, but by two different values in each.

Code:
<set name="relationships">
         <key property-ref="relationshipId" />
         <element type="com.swbyjeff.Relationship" />
         <loader query-ref="loadRelationships" />
      </set>

   <sql-query name="loadRelationships" cacheable="true"
      read-only="true">
      <return alias="r" class="Relationship" />
      SELECT ID {r.id}, OWNER {r.owner}, RANK {r.rank} FROM
      RELATIONSHIP {r} WHERE OWNER=?
   </sql-query>


From the first hours' efforts I believe I've determined that the problem lies in org.hibernate.collection.PersistentSet, or org.hibernate.collection.PersistentBag when using <bag/> in the mapping. The PersistentSet.set is never created when loaded as mapped above.

The PersistentSet.iterator() tries to return simply PersistentSet.set.iterator(), but no point prior to this is the set member, well, set. The constructor that is called doesn't do it, and never are any of the methods where "set =" is used called.

I am still debugging further to determine if this is a problem with my Hibernate configuration (in the previous post), database, or other configuration. I will follow up with more.


Top
 Profile  
 
 Post subject: HIBERNATE BUG FOR LONG TIME?
PostPosted: Fri May 02, 2008 4:22 pm 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
Evidently this has been happening for some time, this un-instantiated set/bag problem. It's even been on this forum before http://forum.hibernate.org/viewtopic.php?p=2382170 and http://forum.hibernate.org/viewtopic.php?t=982986 and http://forum.hibernate.org/viewtopic.php?t=961965 and http://forum.hibernate.org/viewtopic.php?t=980253 just to name a few!

How has no one fixed this in a whole year?

The problem, as near as I've been able to nail it down, is that when the result set is finally gathered, it is simply discarded. Here is the bit (note the list() at the end) in NamedQueryCollectionInitializer that seems to finally get to getting the data. Note that the method (nay, class) at this point has no reference to the collection (PersistedSet or PersistedBag or whatever), and cannot therefore provide the collection with the results!

Code:
   public void initialize(Serializable key, SessionImplementor session)
   throws HibernateException {
      
      if ( log.isDebugEnabled() ) {
         log.debug(
               "initializing collection: " +
               persister.getRole() +
               " using named query: " +
               queryName
            );
      }
      
      //TODO: is there a more elegant way than downcasting?
      AbstractQueryImpl query = (AbstractQueryImpl) session.getNamedSQLQuery(queryName);
      if ( query.getNamedParameters().length>0 ) {
         query.setParameter(
               query.getNamedParameters()[0],
               key,
               persister.getKeyType()
            );
      }
      else {
         query.setParameter( 0, key, persister.getKeyType() );
      }
      query.setCollectionKey( key )
            .setFlushMode( FlushMode.MANUAL )
            .list();

   }


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 05, 2008 3:15 pm 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
Below is my first-pass correction to the NamedQueryCollectionInitializer. This is the "deepest" point in the process where the calls are specific to my problem, If I go into query.list() then I start to run into other bits that are used by other things, and I don't want to break Hibernate.

I was incorrect in the assessment above that the Collection was not available; it's buried in the SessionImplementor.

My fix is essentially to stick the List gathered by the Query into my Collection. I'm double-checking, but in my tests so far, this fix works for bag, set, map, list, and array that are loaded with a named query.

One nice thing, and potential pitfall, is that now that the collection is initialized and remembered, each of the calls to the PersistentCollection objects (toString, iterator, etc.) will see that the collection has been initialized and will not do it again. I'm making some assumptions that there's Hibernate goodness to handle dirty collections and all that.

Additionally, the fix will see all of the "identical" collections in the current session and update them all.

I'm sure there's a much simpler way to get the objects from the List into the PersistentCollection, but in three days of searching, I haven't found any that don't involve heavy specifics (e.g., instanceof), or that run the risk of missing one of the other PersistentCollection subclasses.

Code:
public void initialize(Serializable key, SessionImplementor session)
         throws HibernateException {

      if (log.isDebugEnabled()) {
         log.debug("initializing collection: " + persister.getRole()
               + " using named query: " + queryName);
      }

      // TODO: is there a more elegant way than downcasting?
      AbstractQueryImpl query = (AbstractQueryImpl) session
            .getNamedSQLQuery(queryName);
      if (query.getNamedParameters().length > 0) {
         query.setParameter(query.getNamedParameters()[0], key, persister
               .getKeyType());
      } else {
         query.setParameter(0, key, persister.getKeyType());
      }

      List list = query.setCollectionKey(key).setFlushMode(FlushMode.MANUAL)
            .list();

      // Uh, how 'bout we save the collection for later retrieval?
      CollectionKey collectionKey = new CollectionKey(persister, key, session
            .getEntityMode());
      for (Object object : session.getPersistenceContext()
            .getCollectionsByKey().keySet()) {
         if (collectionKey.equals(object)) {
            PersistentCollection persistentCollection = session
                  .getPersistenceContext().getCollection(collectionKey);

            Serializable[] serializables = new Serializable[list.size()];
            for (int i = 0; i < list.size(); i++) {
               serializables[i] = persister.getElementType().disassemble(
                     list.get(i), session,
                     persistentCollection.getOwner());
            }

            persistentCollection.initializeFromCache(persister,
                  serializables, persistentCollection.getOwner());
            persistentCollection.setSnapshot(key, persistentCollection
                  .getRole(), serializables);

            persistentCollection.afterInitialize();

            session.getPersistenceContext().getCollectionEntry(
                  persistentCollection).postInitialize(
                  persistentCollection);
         }
      }
   }


Top
 Profile  
 
 Post subject: Having same problem, Is there a jira task on this problem
PostPosted: Wed May 07, 2008 10:56 pm 
Newbie

Joined: Tue May 06, 2008 10:31 pm
Posts: 1
Hi,

is there a jira issue on this bug.. I didn't find one.. I am wondering if you have already looked for jira task... If jira issue is open, they would fix it and release the new version..

Thanks


Top
 Profile  
 
 Post subject: JIRA task for this issue created
PostPosted: Thu May 08, 2008 2:12 am 
Newbie

Joined: Thu Jun 16, 2005 6:44 pm
Posts: 6
Location: Salt Lake City, UT
I created a JIRA task that will hopefully get the attention of some of the Hibernate committers.

http://opensource.atlassian.com/project ... e/HHH-3273


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 08, 2008 2:28 pm 
Newbie

Joined: Thu May 01, 2008 7:35 am
Posts: 7
Location: Minneapolis, MN
Thanks for that. I was going to get around to trying to figure out how to get that going.

Hopefully the solution I provided isn't too far off the mark. It seems like I brute-forced the collection and snapshot more than should be necessary, but it met my needs, and certainly addresses the problem.

I've been asked by others how to implement this without rebuilding the Hibernate JAR, and the answer is pretty straight forward, but, unfortunately (or not as your skills and interest allow), you still need the source.

Essentially, the answer lies in the Java classpath.

Simply find the class com.hibernate.persister.collection.NamedQueryCollectionInitializer in the Hibernate source. Add the package and class to your project's source tree and add the fix noted above to that copy of the class. Ensure that your binaries (JAR, whatever) are before the Hibernate JAR in your classpath, and your version of the class will be used instead.

This will, among other things, allow one to ensure that the fix is applied to whatever version of Hibernate is in use, although, as I recall off the top of my head, the same file exists in 3.2.1 and 3.2.6 without change.

Thanks again for the JIRA help. I thought no one had noticed my plea and eventual solution.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.