-->
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.  [ 3 posts ] 
Author Message
 Post subject: Exception with my UserType conversion-what am I doing wrong?
PostPosted: Tue Jan 06, 2004 6:41 pm 
Beginner
Beginner

Joined: Wed Oct 08, 2003 4:22 pm
Posts: 29
I tried to write custom UserType; couldn't find an example to base it on, so went with trial and error. I'm getting an exception with my "CollectionUserType". The intent is to serialize a Collection member variable to a VARCHAR column. Could somebody tell me what I'm doing wrong?


Here is my o/r mapping file:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping.dtd">
<hibernate-mapping>
   <class name="com.teradata.tap.component.system.resultset.ResultSetVO" table="TapResultset">
      <id name="id" column="ID" type="long">
         <generator class="assigned"/>
      </id>
      <property name="label" column="Label"/>
      <property name="columnValueTypes" column="ColumnTypeVector" type="net.sf.hibernate.CollectionUserType" />
      <many-to-one name="query" class="com.teradata.tap.component.system.query.QueryVO" column="QueryId" />
   </class>
</hibernate-mapping>



Here is the exeption I'm getting when it tries to get a value using the conversion:

Code:
14:28:32,880 ERROR [PersistenceManagerBean] PersistenceManager.getVector(klass,
namespace, acl) failed
java.lang.NullPointerException
        at net.sf.hibernate.CollectionUserType.nullSafeGet(CollectionUserType.ja
va:126)
        at net.sf.hibernate.type.CustomType.nullSafeGet(CustomType.java:97)
        at net.sf.hibernate.type.AbstractType.hydrate(AbstractType.java:66)
        at net.sf.hibernate.loader.Loader.hydrate(Loader.java:419)
        at net.sf.hibernate.loader.Loader.loadFromResultSet(Loader.java:373)
        at net.sf.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:342)
        at net.sf.hibernate.loader.Loader.getRow(Loader.java:281)
        at net.sf.hibernate.loader.Loader.doFind(Loader.java:159)
        at net.sf.hibernate.loader.Loader.find(Loader.java:620)
        at net.sf.hibernate.loader.CriteriaLoader.list(CriteriaLoader.java:81)
        at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:3157)
        at net.sf.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:65)
        at com.teradata.tap.system.persistence.ejb.PersistenceManagerBean.getVec
tor(PersistenceManagerBean.java:982)


Here is the code for the "CollectionUserType" I wrote:

Code:
package net.sf.hibernate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.Vector;
import java.util.Collection;
import java.util.Iterator;

/**
* Created by IntelliJ IDEA.
* User: ab210009
* Date: Dec 9, 2003
* Time: 2:00:16 PM
* To change this template use Options | File Templates.
*/
public class CollectionUserType implements UserType {

    private static final String NULLVALUE = "#NULL#";
    private static final String EMPTYCOLLEC = "#EMTPY#";
    private static final String SEPARATOR = "#";

    protected Class objectClass = Collection.class;

    public static final int[] SQL_TYPES = {Types.VARCHAR};

    public CollectionUserType() {
    }

    /**
     * Return the SQL type codes for the columns mapped by this type. The
     * codes are defined on <tt>java.sql.Types</tt>.
     * @see java.sql.Types
     * @return int[] the typecodes
     */
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    /**
     * The class returned by <tt>nullSafeGet()</tt>.
     *
     * @param session
     * @return Class
     */
    public Class returnedClass() {
        return objectClass;
    }

    /**
     * Compare two instances of the class mapped by this type for persistence
     * "equality", ie. equality of persistent state.
     *
     * @param x
     * @param y
     * @return boolean
     */
    public boolean equals(Object x, Object y) throws HibernateException {
        if (x == null && y == null)
            return true;
        else if (x == null)
            return false;
        else if (y == null)
            return false;
        else {
            // Check if non-null Collections are equal
            Collection xx = (Collection)x;
            Collection yy = (Collection)y;
            if (xx.size() != yy.size())
                return false;
            Iterator ix = xx.iterator();
            Iterator iy = yy.iterator();
            // If any elements don't match return false
            while (ix.hasNext()) {
                if (ix.next() != iy.next())
                    return false;
            }
            return true;
        }

    }

    /**
     * Retrieve an instance of the mapped class from a JDBC resultset. Implementors
     * should handle possibility of null values.
     *
     * @param rs a JDBC result set
     * @param names the column names
     * @param owner the containing entity
     * @return Object
     * @throws HibernateException
     * @throws java.sql.SQLException
     */
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {

        // Only 1 column
        Object obj = rs.getObject(names[0]);
        if (obj != null && obj.toString().length() > 0 && !obj.toString().equalsIgnoreCase(NULLVALUE)) {

            Vector v = new Vector();
            String input = obj.toString();
            int pos = input.indexOf(SEPARATOR);

            while (pos >= 0)
            {
                if (pos == 0)
                {
                    v.add("");
                }
                else
                {
                    v.add(input.substring(0, pos));
                }

                if (pos + 1 > input.length()) //# at end causes outof bounds
                {
                    break;
                }

                input = input.substring(pos + 1, input.length());
                pos = input.indexOf(SEPARATOR);
            }
            return v;

        } else if (obj.toString().equalsIgnoreCase(EMPTYCOLLEC)) {
            return new Vector();
        } else {
            return null;
        }
    }

    /**
     * Write an instance of the mapped class to a prepared statement. Implementors
     * should handle possibility of null values. A multi-column type should be written
     * to parameters starting from <tt>index</tt>.
     *
     * @param st a JDBC prepared statement
     * @param obj the object to write
     * @param index statement parameter index
     * @throws HibernateException
     * @throws java.sql.SQLException
     */
    public void nullSafeSet(PreparedStatement st, Object obj, int index) throws HibernateException, SQLException {

        if (obj == null)
        {
            // Set null string symbol in PreparedStatement and return
            st.setString(index, NULLVALUE);
            return;
        }

        if (!(obj instanceof Collection))
        {
            throw new HibernateException(
                "Object is not a Collection it is a" + obj.getClass().getName());
        }

        Vector v = (Vector) obj;
        if (v.size() == 0)
        {
            // Set null string symbol in PreparedStatement and return
            st.setString(index, NULLVALUE);
            return;
        }

        StringBuffer result = new StringBuffer();
        for (int i = 0; i < v.size(); i++)
        {
            String newSt = v.get(i).toString();
            if (newSt.indexOf(SEPARATOR) >= 0)
            {
                throw new HibernateException(
                    "An entry in the Vector contains the forbidden "
                        + SEPARATOR
                        + " character used to separate the strings on the DB");
            }
            result.append(newSt);
            result.append(SEPARATOR);
        }

        // Set string in PreparedStatement
        st.setString(index, result.toString());
    }

    /**
     * Return a deep copy of the persistent state, stopping at entities and at
     * collections.
     *
     * @return Object a copy
     */
    public Object deepCopy(Object value) throws HibernateException {
        if (value == null)
            return null;

        Vector copy = null;
        try {
            copy = new Vector();
            Vector orig = (Vector)value;
            for (int i=0; i<orig.size(); i++) {
                copy.add( orig.get(i) );
            }
        } catch (ClassCastException ex) {
            ex.printStackTrace();
        }

        return copy;
    }

    /**
     * Are objects of this type mutable?
     *
     * @return boolean
     */
    public boolean isMutable() {
        return true;
    }

}



[/quote]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2004 7:58 pm 
Pro
Pro

Joined: Tue Aug 26, 2003 8:07 pm
Posts: 229
Location: Brisbane, Australia
The audit info design pattern wiki page has an example of a user type, that might be some help:
http://www.hibernate.org/48.html

It does bring up the point that hibernate could really use some better/more formal/easier to find documentation on how to go about writing UserType and CompositeUserType implementations though.

_________________
Cheers,
Shorn.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2004 8:02 pm 
Beginner
Beginner

Joined: Wed Oct 08, 2003 4:22 pm
Posts: 29
Thanks for the tip, will take a look at the Audit type implementation. Turned out the immediate problem was an error on my part, should have had an obj != null check in the 2nd clause.

Code:
       
       } else if (obj != null && obj.toString().equalsIgnoreCase(EMPTYCOLLEC)) {
            return new Vector();


However, I'm troubleshooting another issue now, not sure if it's related...


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