Mapping a Clob to a String[ http://www.hibernate ]

Mapping a Clob to a String

Hibernate 1.2.3 has built-in support for clobs. Hibernate natively maps clob columns to java.sql.Clob. However, it's sometimes useful to read the whole clob into memory and deal with it as a String.

One approach for doing this to create a new UserType as follows.

I don't think this is the best implementation on some platforms - better to get/set character streams rather than get / set Clobs - GK

package mypackage;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.sql.Clob;

import cirrus.hibernate.Hibernate;
import cirrus.hibernate.HibernateException;
import cirrus.hibernate.UserType;

public class StringClobType implements UserType
{
    public int[] sqlTypes()
    {
        return new int[] { Types.CLOB };
    }

    public Class returnedClass()
    {
        return String.class;
    }

    public boolean equals(Object x, Object y)
    {
        return (x == y)
            || (x != null
                && y != null
                && (x.equals(y)));
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
        throws HibernateException, SQLException
    {
        Clob clob = rs.getClob(names[0]);
        return clob.getSubString(1, (int) clob.length());
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index)
        throws HibernateException, SQLException
    {
        st.setClob(index, Hibernate.createClob((String) value));
    }

    public Object deepCopy(Object value)
    {
        if (value == null) return null;
        return new String((String) value);
    }

    public boolean isMutable()
    {
        return false;
    }
}


The StringClobType will convert a clob into a String and back again.

Here's how to use it. First, define an entity that contains a String property:

public class TextValue
{
  private long id;
  private String byte;

  public long getId() { return id; }
  public void setId(long id) { this.id = id; }

  public String getText() { return text; }
  public void setText(String text) { this.text = text; }
}


Then map a clob column onto the String property:

<class name="TextValue" table="TEXT_VALUE">
  <id name="id/>
  <property name="text" column="TEXT" type="mypackage.StringClobType"/>
</class>

Notes:

1) Clobs aren't cachable. By converting the clob into a String, you can now cache the entity.

2) This approach reads the whole clob into memory at once.

3) The above type is known to work for reading clobs out of the db. Other usage patterns might also work.

4) See also Mapping a Blob to a byte[].

*****************************************************************************

Method 2

I could not get the above method to work.

This is based on the cirrus.hibernate.type.Clob source.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.commons.lang.ObjectUtils;
import cirrus.hibernate.type.ImmutableType;

public class TextType extends ImmutableType {

  public Object get(ResultSet rs, String name) throws SQLException {
    String line;
    String str = "";
    BufferedReader b = new BufferedReader( rs.getCharacterStream( name ) );
      try {
        while( (line = b.readLine()) != null ) {
      str += line;
    }
      } catch (IOException e) {
    throw new SQLException( e.toString() );
    }
    return str;
  }

  public Class returnedClass() {
    return String.class;
  }

  public void set(PreparedStatement st, Object value, int index) 
    throws SQLException {
    StringReader r = new StringReader( (String)value );
    st.setCharacterStream( index, r, ((String)value).length() );
  }

  public int sqlType() {
    return Types.CLOB;
  }
    
  public String getName() { return "string"; }

  public boolean hasNiceEquals() {
    return false;
  }

  public boolean equals(Object x, Object y) {
    return ObjectUtils.equals(x, y);
  }

  public String toXML(Object value) {
    return (String) value;
  }
}

********************************

Method 2 does not account for a null clob nor does it append newline charaters.

I would suggest replacing the get method with this.
public Object get(ResultSet rs, String name) throws HibernateException, SQLException
    {
        Reader reader = rs.getCharacterStream(name);
        if (reader == null)
        {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        try
        {
            char[] charbuf = new char[4096];
            for (int i = reader.read(charbuf); i > 0; i = reader.read(charbuf))
            {
                sb.append(charbuf, 0, i);
            }
        }
        catch (IOException e)
        {
            throw new SQLException( e.getMessage() );
        }
        return sb.toString();
    }

你可能感兴趣的:(java,apache,sql,Hibernate,cache)