-->
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.  [ 2 posts ] 
Author Message
 Post subject: CompositeUserType Implementation of JADE.Quantity
PostPosted: Wed Mar 10, 2004 4:26 am 
Newbie

Joined: Mon Feb 23, 2004 8:30 am
Posts: 13
Location: Istanbul, Turkey
Hello,

I use JADE library which provides ready classes for lots of physical quantities. I want to store the physical quantity in the database. To do this I implemented the CompositeUserType interface.

But there must be an error in my mapping file or CompositeUserType implementation. When Hibernate runs the Configuration, a MappingException is thrown, which says "property mapping has wrong number of columns".

The Hibernate version is: 2.1

Trace of exception:

Code:
net.sf.hibernate.MappingException: property mapping has wrong number of columns: testJADE.SimpleQuantity.quantity type: com.dautelle.units.CustomQuantity
   at net.sf.hibernate.mapping.PersistentClass.validate(PersistentClass.java:269)
   at net.sf.hibernate.mapping.RootClass.validate(RootClass.java:199)
   at net.sf.hibernate.cfg.Configuration.validate(Configuration.java:587)
   at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:744)
   at testJADE.Main.configure(Main.java:16)


The exception is thrown on this line:

Code:
        sf = new Configuration()
            .addClass(SimpleQuantity.class)
            .buildSessionFactory();


SimpleQuantity is a very simple Hibernate persistable class:

Code:
public class SimpleQuantity {
    Long id;
    Quantity quantity;
    // getter/setters


Quantity is a class from JADE library. It stores the amount inside a range of max and min amounts. It also stores the physical unit of the amount. Since it doesn't provide the accessors needed to map it as a component, I defined my own custom type.

Code:
public class CustomQuantity implements CompositeUserType{
    public String[] getPropertyNames() {
        return new String[]{"minimum","systemUnit"};
    }
    public Type[] getPropertyTypes() {
        return new Type[]{ Hibernate.DOUBLE, Hibernate.OBJECT };
    }
    public Object getPropertyValue(Object component, int property) {
        Quantity q = ((Quantity) component);
        if( property == 0 ){
            return new Double((q.getMinimum() + q.getMaximum())/2.0);
        }
        if( property == 1 ){
            return q.getSystemUnit();
        }
        return null;
    }
    public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
    }
    public Class returnedClass() {
        return Quantity.class;
    }
    public boolean equals(Object x, Object y) throws HibernateException {
        return x.equals(y);
    }
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
        Double amount = (Double) Hibernate.DOUBLE.nullSafeGet(rs, names[0]);
        String symbol = (String) Hibernate.STRING.nullSafeGet(rs, names[1]);

        return ( amount==null && symbol==null ) ? null :
                Quantity.valueOf(amount.doubleValue(),BaseUnit.getInstance(symbol)) ;
    }
    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
        double min = ((Quantity) value).getMinimum();
        double max = ((Quantity) value).getMaximum();
        Double result = new Double((min+max)/2.0);

        String symbol = ((Quantity) value).getSystemUnit().getSystemUnit()._symbol;

        Hibernate.DOUBLE.nullSafeSet(st, result, index);
        Hibernate.STRING.nullSafeSet(st, symbol, index+1);
    }
    public Object deepCopy(Object value) throws HibernateException {
        if ( value == null) return null;
        Quantity q = (Quantity) value;
        return Quantity.valueOf((q.getMinimum()+q.getMaximum())/2.0,q.getSystemUnit());
    }
    public boolean isMutable() {
        return false;
    }
    public Serializable disassemble(Object value, SessionImplementor session) throws HibernateException {
        return (Serializable) deepCopy(value);
    }
    public Object assemble(Serializable cached, SessionImplementor session, Object owner) throws HibernateException {
        return (Serializable) deepCopy(cached);
    }
}


I debugged the code. The cause of the exception lies in SimpleValue.isValid().

Code:
   public boolean isValid(Mapping mapping) throws MappingException {
      return getColumnSpan()==getType().getColumnSpan(mapping);
   }


Here getColumnSpan() returns 2. Whereas getType().getColumnSpan(mapping) returns 3.

What I didn't understand is the value 3. Actually I defined only 2 columns in my mapping file for CustomQuantity.

Code:
<hibernate-mapping>
    <!-- testJADE.SimpleQuantity root -->
    <class name="testJADE.SimpleQuantity" table="SimpleQuantity">
        <id name="id" type="long" column="id">
            <generator class="native"/>
        </id>
        <property name="quantity" type="com.dautelle.units.CustomQuantity">
            <column name="minimum"/>
            <column name="unit"/>
        </property>
    </class>
</hibernate-mapping>


May you guess, where might be the problem? Where should I look?

If you may send me some simple CompositeUserType examples, I would appreciate. I reviewed DoubleStringType and MultiplicityType examples in Hibernate test package, although I couldn't run MultiplicityType example.

Thanks for your interest.


Top
 Profile  
 
 Post subject: Resolved
PostPosted: Wed Mar 10, 2004 8:37 am 
Newbie

Joined: Mon Feb 23, 2004 8:30 am
Posts: 13
Location: Istanbul, Turkey
I resolved the problem. I defined getPropertyTypes() method mistakenly. The correct method should be:

Code:
    public Type[] getPropertyTypes() {
        return new Type[]{ Hibernate.DOUBLE, Hibernate.STRING };
    }


Formerly, instead of Hibernate.STRING, it was Hibernate.OBJECT.

_________________
Mert Nuhoglu
http://jroller.com/page/mnuhoglu


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.