2011-01-20 67 views
7

我們一直在使用GenericEnumUserType作爲我們的可擴展枚舉,而我們的類無法在JBoss 6中的Hibernate 3.6+容器中加載。關於休眠特定usertype的java.lang.verifyError

以下錯誤拋出

#abc state=Create: java.lang.NoSuchMethodError: org.hibernate.type.Type 
Factory.basic(Ljava/lang/String;)Lorg/hibernate/type/Type; 

以下代碼

type = (NullableType)TypeFactory.basic(identifierType.getName()); 

回答

11

不幸的是,如果您需要基於Enum的序號或名稱之外的其他內容序列化,@Enumerated不起作用。我設法找到了解決方案(從here稍微修改)。

import java.io.Serializable; 
import java.lang.reflect.Method; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.Properties; 
import org.hibernate.HibernateException; 
import org.hibernate.type.AbstractSingleColumnStandardBasicType; 
import org.hibernate.type.TypeResolver; 
import org.hibernate.usertype.ParameterizedType; 
import org.hibernate.usertype.UserType; 

public class GenericEnumUserType implements UserType, ParameterizedType { 

    private Class<? extends Enum> enumClass; 
    private Class<?> identifierType; 
    private Method identifierMethod; 
    private Method valueOfMethod; 
    private static final String defaultIdentifierMethodName = "name"; 
    private static final String defaultValueOfMethodName = "valueOf"; 
    private AbstractSingleColumnStandardBasicType type; 
    private int[] sqlTypes; 

    @Override 
    public void setParameterValues(Properties parameters) 
    { 
     String enumClassName = parameters.getProperty("enumClass"); 
     try 
     { 
      enumClass = Class.forName(enumClassName).asSubclass(Enum.class); 
     } 
     catch (ClassNotFoundException exception) { 
      throw new HibernateException("Enum class not found", exception); 
     } 

     String identifierMethodName = parameters.getProperty("identifierMethod", defaultIdentifierMethodName); 

     try 
     { 
      identifierMethod = enumClass.getMethod(identifierMethodName, 
                new Class[0]); 
      identifierType = identifierMethod.getReturnType(); 
     } 
     catch (Exception exception) 
     { 
      throw new HibernateException("Failed to optain identifier method", 
        exception); 
     } 

     TypeResolver tr = new TypeResolver(); 
     type = (AbstractSingleColumnStandardBasicType)tr.basic(identifierType.getName()); 
     if (type == null) 
     { 
      throw new HibernateException("Unsupported identifier type " + identifierType.getName()); 
     } 
     sqlTypes = new int[] { type.sqlType() }; 

     String valueOfMethodName = parameters.getProperty("valueOfMethod", 
                  defaultValueOfMethodName); 

     try 
     { 
      valueOfMethod = enumClass.getMethod(valueOfMethodName, 
               new Class[] { identifierType }); 
     } 
     catch (Exception exception) 
     { 
      throw new HibernateException("Failed to optain valueOf method", 
              exception); 
     } 
    } 

    @Override 
    public Class returnedClass() 
    { 
     return enumClass; 
    } 

    @Override 
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) 
     throws HibernateException, SQLException 
    { 
     Object identifier = type.get(rs, names[0]); 
     try 
     { 
      return valueOfMethod.invoke(enumClass, new Object[] { identifier }); 
     } 
     catch (Exception exception) 
     { 
      throw new HibernateException("Exception while invoking valueOfMethod of enumeration class: ", 
              exception); 
     } 
    } 

    public void nullSafeSet(PreparedStatement st, Object value, int index) 
     throws HibernateException, SQLException 
    { 
     try 
     { 
      Object identifier = value != null ? identifierMethod.invoke(value, 
                     new Object[0]) : null; 
      st.setObject(index, identifier); 
     } 
     catch (Exception exception) 
     { 
      throw new HibernateException("Exception while invoking identifierMethod of enumeration class: ", 
              exception); 

     } 
    } 

    @Override 
    public int[] sqlTypes() 
    { 
     return sqlTypes; 
    } 

    @Override 
    public Object assemble(Serializable cached, Object owner) 
     throws HibernateException 
    { 
     return cached; 
    } 

    @Override 
    public Object deepCopy(Object value) 
     throws HibernateException 
    { 
     return value; 
    } 

    @Override 
    public Serializable disassemble(Object value) 
     throws HibernateException 
    { 
     return (Serializable) value; 
    } 

    @Override 
    public boolean equals(Object x, Object y) 
     throws HibernateException 
    { 
     return x == y; 
    } 

    @Override 
    public int hashCode(Object x) 
     throws HibernateException 
    { 
     return x.hashCode(); 
    } 

    public boolean isMutable() 
    { 
     return false; 
    } 

    public Object replace(Object original, Object target, Object owner) 
     throws HibernateException 
    { 
     return original; 
    } 
} 
2

有處於休眠3.6沒有TypeFactory.basic(字符串)了。比較的javadoc:

http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/type/TypeFactory.html http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/type/TypeFactory.html

我認爲現在是時候從移動自定義UserType到標準@Enumerated :-)

+4

不幸的是,如果您是基於枚舉序號或名稱進行序列化,則只能使用@Enumerated。有些情況下這不合適。 – mtpettyp 2011-06-03 19:27:57