java.lang.verifyError для конкретного пользовательского типа в спящем режиме - PullRequest
7 голосов
/ 20 января 2011

Мы использовали GenericEnumUserType для наших расширяемых перечислений, и наши классы не могут загрузиться в JBoss 6 в контейнере Hibernate 3.6+.

Выдается следующая ошибка

#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());

Ответы [ 2 ]

11 голосов
/ 03 июня 2011

К сожалению, @Enumerated не работает, если вам нужно сериализовать на основе чего-то другого, кроме порядкового номера или имени Enum. Мне удалось найти решение (слегка изменено с здесь ).

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 голосов
/ 20 января 2011

В Hibernate 3.6 больше нет TypeFactory.basic (String). Сравните 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: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...