-->
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.  [ 1 post ] 
Author Message
 Post subject: Invalid results from "wrong way" one-to-one query?
PostPosted: Thu Nov 18, 2004 5:10 pm 
Newbie

Joined: Tue Nov 16, 2004 1:10 pm
Posts: 5
Suppose you have a one-to-one "property-ref" mapping between two tables.
It seems that Hibernate queries from the "pointed-to" end return invalid results.

In this example, the query returns results that don't match the query criteria.
We search for Assets that have tag != null yet some returned Assets have
tag == null.

Is this a bug? Or am I doing something incorrectly? If the latter, any pointers
to the relevant documentation are appreciated.

Hibernate version: 2.1.6

Mapping documents:

This is HBug$Asset.hbm.xml:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
    <class name="HBug$Asset" dynamic-update="false"
      dynamic-insert="false" select-before-update="false"
      optimistic-lock="version" table="Asset">
        <id name="id" column="id" type="java.lang.Long">
            <generator class="native"/>
        </id>
        <one-to-one name="tag" class="HBug$Tag" cascade="save-update"
          outer-join="auto" constrained="false" property-ref="asset"/>
        <property name="bool" type="boolean" update="true" insert="true"
          access="property" column="bool" not-null="true"/>
    </class>
</hibernate-mapping>


This is HBug$Tag.hbm.xml:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
    <class name="HBug$Tag" dynamic-update="false"
      dynamic-insert="false" select-before-update="false"
      optimistic-lock="version" table="Tag">
        <id name="id" column="id" type="java.lang.Long">
            <generator class="native"/>
        </id>
        <many-to-one name="asset" class="HBug$Asset" cascade="save-update"
          outer-join="auto" update="true" insert="true" access="property"
          column="asset" unique="true"/>
    </class>
</hibernate-mapping>


MySQL tables:

Code:
#
# Table structure for table `Asset`
#

CREATE TABLE `Asset` (
  `id` bigint(20) NOT NULL auto_increment,
  `type` varchar(16) NOT NULL default '',
  `name` varchar(255) default NULL,
  `bool` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM;

# --------------------------------------------------------

#
# Table structure for table `Tag`
#

CREATE TABLE `Tag` (
  `id` bigint(20) NOT NULL auto_increment,
  `asset` bigint(20) default NULL,
  PRIMARY KEY  (`id`)
) TYPE=MyISAM;

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

Here is the test program:

Code:
                                                                               
import net.sf.hibernate.*;
import net.sf.hibernate.type.Type;
import net.sf.hibernate.cfg.Configuration;
import java.io.Serializable;
import java.util.*;

public class HBug {

    public static abstract class Updater {
        private final String info;
        public Updater(String info) {
            this.info = info;
        }
        public abstract void update(Session session) throws HibernateException;
        public String toString() {
            return info;
        }
    }

    public static class Asset {
        private Long id;
        private Tag tag;
        private boolean bool;
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public Tag getTag() { return tag; }
        public void setTag(Tag tag) { this.tag = tag; }
        public boolean getBool() { return bool; }
        public void setBool(boolean bool) { this.bool = bool; }
        public String toString() {
          return "Asset[id="+id+",tag="
            +(tag != null ? ""+tag.id : "null")+",bool="+bool+"]";
        }
    }

    public static class Tag {
        private Long id;
        private Asset asset;
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public Asset getAsset() { return asset; }
        public void setAsset(Asset asset) { this.asset = asset; }
        public String toString() {
          return "Tag[id="+id+",asset="
            +(asset != null ? ""+asset.id : "null")+"]";
        }
    }

    private static final Class[] PERSISTENT_CLASSES = {
        Asset.class,
        Tag.class,

    };

    private static SessionFactory sessionFactory;

    public static void main(String[] args) throws Exception {

        // Configure Hibernate
        Configuration config = new Configuration();
        for (int i = 0; i < PERSISTENT_CLASSES.length; i++)
            config.addClass(PERSISTENT_CLASSES[i]);
        sessionFactory = config.buildSessionFactory();

        // Initialize database
        update(new Updater("initializing database") {
            public void update(Session session) throws HibernateException {

                // Create asset and assigned tag
                Asset asset = new Asset();
                Tag tag = new Tag();
                asset.setTag(tag);
                asset.setBool(true);
                tag.setAsset(asset);
                session.save(tag);
                System.out.println("saved " + tag);
                session.save(asset);
                System.out.println("saved " + asset);

                // Create unassigned asset
                asset = new Asset();
                asset.setBool(true);
                session.save(asset);
                System.out.println("saved " + asset);
            }
        });

        // Read back tag and asset
        update(new Updater("searching for 'true' assets with tags assigned") {
            public void update(Session session) throws HibernateException {
                List list = session.createQuery(
                  "from HBug$Asset as asset where asset.bool=true"
                  + " and asset.tag is not null").list();
                for (Iterator i = list.iterator(); i.hasNext(); ) {
                    Asset asset = (Asset)i.next();
                    System.out.println("  GOT: " + asset);
                    if (asset.getTag() == null)
                        System.out.println("  --> but tag is null!");
                }
            }
        });

        // Done
        System.out.println("done");
    }

    private static void update(Updater updater) throws HibernateException {
        System.out.println(">>> creating session for: " + updater);
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        boolean success = false;
        try {
            tx = session.beginTransaction();
            updater.update(session);
            tx.commit();
            success = true;
        } finally {
            if (!success && (tx != null))
                tx.rollback();
            System.out.println("<<< closing session for: " + updater);
            session.close();
        }
    }
}


Name and version of the database you are using: MySQL 3.23.54

The generated SQL (show_sql=true):

Here is the program output:

Code:
>>> creating session for: initializing database
Hibernate: insert into Asset (bool) values (?)
Hibernate: insert into Tag (asset) values (?)
saved Tag[id=1,asset=1]
saved Asset[id=1,tag=1,bool=true]
Hibernate: insert into Asset (bool) values (?)
saved Asset[id=2,tag=null,bool=true]
<<< closing session for: initializing database
>>> creating session for: searching for 'true' assets with tags assigned
Hibernate: select hbug_asset0_.id as id, hbug_asset0_.bool as bool from Asset hbug_asset0_ where (hbug_asset0_.bool=1 )and(hbug_asset0_.id is not null )
Hibernate: select hbug_tag0_.id as id1_, hbug_tag0_.asset as asset1_, hbug_asset1_.id as id0_, hbug_asset1_.bool as bool0_ from Tag hbug_tag0_ left outer join Asset hbug_asset1_ on hbug_tag0_.asset=hbug_asset1_.id where hbug_tag0_.asset=?
Hibernate: select hbug_tag0_.id as id1_, hbug_tag0_.asset as asset1_, hbug_asset1_.id as id0_, hbug_asset1_.bool as bool0_ from Tag hbug_tag0_ left outer join Asset hbug_asset1_ on hbug_tag0_.asset=hbug_asset1_.id where hbug_tag0_.asset=?
  GOT: Asset[id=1,tag=1,bool=true]
  GOT: Asset[id=2,tag=null,bool=true]
  --> but tag is null!
<<< closing session for: searching for 'true' assets with tags assigned
done


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

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.