2011-01-20 10 views
7

हम अपने विस्तारणीय गणनाओं के लिए GenericEnumUserType का उपयोग कर रहे हैं और हमारी कक्षाएं जेबॉस 6 में एक हाइबरनेट 3.6+ कंटेनर पर लोड करने में विफल रही हैं।java.lang.verify हाइबरनेट विशिष्ट usertype पर त्रुटि

निम्न त्रुटि निम्न कोड

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

उत्तर

11

दुर्भाग्यवश @ एन्युमेरेटेड काम नहीं करता है अगर आपको एनम के सामान्य या नाम के अलावा किसी अन्य चीज़ के आधार पर क्रमबद्ध करने की आवश्यकता है। मैंने एक समाधान खोजने में कामयाब रहा है (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

पर

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

फेंक दिया जाता है कोई TypeFactory.basic (स्ट्रिंग) हाइबरनेट 3.6 में अब और नहीं है। javadocs की तुलना करें:

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

मुझे लगता है कि यह अब एक से स्थानांतरित करने के लिए समय आ गया है कस्टम यूजर टाइप मानक @Enumerated :-)

+4

दुर्भाग्यवश यदि आप एनम ऑर्डिनल या नाम के आधार पर क्रमबद्ध कर रहे हैं तो आप केवल @Enumerated का उपयोग कर सकते हैं। ऐसे मामले हैं जब यह उचित नहीं है। – mtpettyp

+1

मैं पुष्टि कर सकता हूं कि mtpettyp क्या कह रहा है। इसके लिए एक आम मामला तब होता है जब आपने 'जादू संख्या' को enum के साथ बदल दिया, लेकिन आपको अभी भी मूल डेटा रखना होगा। – samspot

संबंधित मुद्दे