0

我使用 Spring-orm 4.3.30 。在 Hibernate 5.1.17 中,createSqlQuery 类使用 AbstractQueryImpl,我们可以将 Custom Type 与 prepareStatement 一起使用

例如 :

prepareStatement.setParameter(2, reportingYear.getEndMonth(), YearMonthType.class)

AbstractQueryImpl :

public Query setParameter(int position, Object val, Type type) {
        if ( parameterMetadata.getOrdinalParameterCount() == 0 ) {
            throw new IllegalArgumentException( "No positional parameters in query: " + getQueryString() );
        }
        if ( position < 0 || position > parameterMetadata.getOrdinalParameterCount() - 1 ) {
            throw new IllegalArgumentException( "Positional parameter does not exist: " + position + " in query: " + getQueryString() );
        }
        int size = values.size();
        if ( position < size ) {
            values.set( position, val );
            types.set( position, type );
        }
        else {
            // prepend value and type list with null for any positions before the wanted position.
            for ( int i = 0; i < position - size; i++ ) {
                values.add( UNSET_PARAMETER );
                types.add( UNSET_TYPE );
            }
            values.add( val );
            **types.add( type );**
        }
        return this;
    }

从 Hibernate 5.2 开始,它使用:NativeQueryImpl

当我们使用自定义类型的 prepareStatement 时。

NativeQueryImpl 尝试使用 SessionFactoryImpl.resolveParameterBindType 解析自定义类型

@Override
    public Type resolveParameterBindType(Class clazz){
        String typename = clazz.getName();      
Type type = getTypeResolver().heuristicType( typename ); 

        boolean serializable = type != null && type instanceof SerializableType;
        if ( type == null || serializable ) {
            try {
                getMetamodel().entityPersister( clazz.getName() );
            }
            catch (MappingException me) {
                if ( serializable ) {
                    return type;
                }
                else {
                    throw new HibernateException( "Could not determine a type for class: " + typename );
                }
            }
            return getTypeHelper().entity( clazz );
        }
        else {
            return type;
        }
    }

打电话时:

Type type = getTypeResolver().heuristicType( typename );

TypeResolver 中没有自定义类型。

/**
     * Retrieve the {@link Type} resolver associated with this factory.
     *
     * @return The type resolver
     *
     * @deprecated (since 5.3) No replacement, access to and handling of Types will be much different in 6.0
     */
    @Deprecated
    public TypeResolver getTypeResolver() {
        return metamodel.getTypeConfiguration().getTypeResolver();
    }

知道@TypDef 不起作用。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.tennaxia.t3.reporting.bo">
    <typedef name="YearMonth" class="com.tennaxia.t3.common.date.YearMonthType" />

知道使用 JPQL,自定义类型与 setParameter 一起使用。

如何注册我的自定义类型并且可以与 Sql 本机查询一起使用?

另一种解决方案是在 QueryParameterBindingsImpl.parameterMetadata 中添加自定义类型,但我再次搜索如何在此 parameterMetadata 中添加此自定义类型。

非常感谢帮助我理解这一点。

4

1 回答 1

0

You can set the parameter with the org.hibernate.engine.spi.TypedValue wrapper which also includes a type.

于 2021-06-30T18:01:26.170 回答