Spring-orm 4.3.30 を使用しています。Hibernate 5.1.17 では、クラス createSqlQuery は AbstractQueryImpl を使用し、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 で型 custom を解決しようとします
@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 に追加する方法をもう一度検索します。
これを理解するのを手伝ってくれてありがとう。