Results 1 to 6 of 6

Thread: initializing hibernate many-to-one relation within Set

  1. #1
    Join Date
    Nov 2004
    Location
    Rural Ireland
    Posts
    36

    Default initializing hibernate many-to-one relation within Set

    Hi,
    I posted the same issue on the hibernate site, but am cross-posting here because it may be spring that I'm getting into difficulty with.
    I'm having some difficulty getting a many-to-one relation initialized. I'm subclassing HibernateDaoSupport class in the class involved.
    What I have is a Batch that contains a Set of transactions. In a certain method I want to load a batch using hibernate by calling the getHibernateTemplate().findByNamedParam() method, passing in the id of the batch. I also need the set of transactions in this case, which I get back by doing a left join fetch in the hql passed in to the spring method mentioned (this is the reason I use hql - I need to specify a left join fetch)
    This all works fine. However here I get into trouble. Each Transaction has 2 many-to-one relations (a transactionCurrency and an errorCode) that I want initialized by this query. I thought the best way to do this was by iterating through the transactions and calling a Hibernate.initialize() for each many-to-one I was interested in initializing. However this seems only to work for the transactionCurrency many-to-one (even though the hibernate-generated select SQL for both many-to-ones appears on the console).
    The code snippet below uses a hardcoded transactional callback. I've tried using a TransactionProxyFactoryBean as well with the same results.
    The errorCode object is always a cglib proxy with null values for both its fields. I'm sure I'm doing something stupid here or there is a trivial mistake in my mappings or transaction. I'd be grateful if anyone could point any problem out, cause I can't see it.
    Here's the spring code
    Code:
        public Batch getBatchWithTransactions(final Long batchID) {
            return (Batch) getHibernateTemplate().execute(new
    HibernateCallback() {
                public Object doInHibernate(final Session session) {
                    Batch batch =  (Batch) session.createQuery(
                            "from myproject.dataobject.Batch b "
                            + "left join fetch b.transactions "
                            + "where b.id
    = :batchID").setParameter("batchID", batchID)
                            .list().get(0);
                    Iterator txns = batch.getTransactions().iterator();
                    while (txns.hasNext()) {
                        Transaction t = (Transaction) txns.next();
                        Hibernate.initialize(t.getErrorCode());
                        Hibernate.initialize(t.getTransactionCurrency());
                    }
                    return batch;
                }
            });
        }

    (relevant parts of 4 different hbm.xml files)
    Batch.hbm.xml
    Code:
    <hibernate-mapping>
         <class name="myproject.dataobject.Batch"
           table="batch">
             <id name="id"
                column="batch_id" type="long">
                 <generator class="native" />
             </id>
            <set name="transactions" inverse="true" cascade="save-update">
                <key column="batch_id" />
                <one-to-many class="myproject.dataobject.Transaction" />
            </set>
         </class>
    </hibernate-mapping>
    transaction.hbm.xml
    Code:
    <hibernate-mapping package="myproject.dataobject">
        <class name="Transaction" table="TRANSACTION">
            <id
                column="TRANSACTION_ID"
                name="id"
                type="long"
                >
                <generator class="native" />
            </id>
            <many-to-one name="batch"
                not-null="true"
                class="myproject.dataobject.Batch"
                cascade="save-update"
                >
                <column name="BATCH_ID" />
            </many-to-one>
            <many-to-one name="errorCode"
                class="myproject.dataobject.lookup.StatusCode"
                column="ERROR_CODE"
                />
            <many-to-one name="transactionCurrency"
                class="myproject.dataobject.Currency"
                column="TRANSACTION_CURRENCY_CODE"
                />
        </class>
    </hibernate-mapping>
    StatusCode.hbm.xml
    Code:
    <hibernate-mapping package="myproject.dataobject">
       <class name="StatusCode" table="STATUS_CODE">
          <id
             column="ERROR_CODE"
             name="id"
             type="integer"
          >
             <generator class="native" />
          </id>
          <property
             column="ERROR_DESCRIPTION"
             length="50"
             name="description"
             not-null="false"
             type="string"
           />
       </class>
    </hibernate-mapping>
    Currency.hbm.xml
    Code:
    <hibernate-mapping>
      <class name="myproject.dataobject.Currency"
          table="currency">
          <id name="isoCode" column="iso_code" type="integer">
              <generator class="sequence">
                  <param name="sequence">acquirer_comm_seq</param>
              </generator>
          </id>
          <property name="swiftCode"
              column="swift_code"
              not-null="true"
              type="string"
              unique="false"
              />
          <property name="name"
              column="description"
              not-null="true"
              type="string"
              unique="false"
              />
          <property name="minorUnits"
              column="minor_units"
              not-null="true"
              type="integer"
              unique="false"
              />
      </class>
    </hibernate-mapping>

  2. #2
    Join Date
    Nov 2004
    Location
    Rural Ireland
    Posts
    36

    Default

    Found the problem. getters in the offending unpopulated object were marked as final, which meant that hibernate could not proxy them.

  3. #3
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    As a work around specify inside the mapping the access to be directly on the field (thus bypassing the getter/setter).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  4. #4
    Join Date
    Aug 2004
    Posts
    1,905

    Default

    BTW: If you tell Hibernate to populate the field, how does Hibernate do dirty detection?

  5. #5
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    That's something internal to Hibernate; AFAIK the proxy will not override the method and will do field interception (as opposed to method interception).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  6. #6
    Join Date
    Aug 2004
    Posts
    1,905

    Default (OFF TOPIC)

    (OFF TOPIC): I see. I assumed (actually guessed ) that hibernate overrode the accessors and set a dirty flag on the setters.

    I suppose it must be a bit more sophisticated.

    Thanks dude

Similar Threads

  1. Loosing my SecureContext
    By sklakken in forum Security
    Replies: 3
    Last Post: Jul 21st, 2005, 01:44 PM
  2. Spring + Hibernate ORA-00936: missing expression
    By Hugh_la_Main in forum Data
    Replies: 1
    Last Post: Jun 28th, 2005, 08:48 AM
  3. Unclosed Hibernate Connection
    By jvargas in forum Data
    Replies: 4
    Last Post: Mar 28th, 2005, 01:24 PM
  4. Replies: 3
    Last Post: Nov 19th, 2004, 07:16 PM
  5. Transaction pb Hibernate/MySQL
    By syluser in forum Data
    Replies: 2
    Last Post: Aug 28th, 2004, 02:40 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •