HHH-12202 Introduce ParameterType.getReturnedJavaType() as companion of getReturnedClass()

This commit is contained in:
Yanming Zhou 2024-03-25 18:43:05 +08:00 committed by Christian Beikov
parent 5c2fb290f5
commit fa2e8f73e7
6 changed files with 191 additions and 2 deletions

View File

@ -26,6 +26,7 @@ import org.hibernate.Remove;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.reflection.java.JavaXMember;
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
@ -71,6 +72,7 @@ import static org.hibernate.internal.util.collections.ArrayHelper.toBooleanArray
* A mapping model object that represents any value that maps to columns.
*
* @author Gavin King
* @author Yanming Zhou
*/
public abstract class SimpleValue implements KeyValue {
private static final CoreMessageLogger log = CoreLogging.messageLogger( SimpleValue.class );
@ -943,6 +945,7 @@ public abstract class SimpleValue implements KeyValue {
classLoaderService.classForTypeName(
typeParameters.getProperty(DynamicParameterizedType.RETURNED_CLASS)
),
xProperty instanceof JavaXMember ? ((JavaXMember) xProperty ).getJavaType() : null,
annotations,
table.getCatalog(),
table.getSchema(),
@ -985,6 +988,7 @@ public abstract class SimpleValue implements KeyValue {
return new ParameterTypeImpl(
classLoaderService.classForTypeName(typeParameters.getProperty(DynamicParameterizedType.RETURNED_CLASS)),
xProperty instanceof JavaXMember ? ((JavaXMember) xProperty ).getJavaType() : null,
annotations,
table.getCatalog(),
table.getSchema(),
@ -1002,6 +1006,7 @@ public abstract class SimpleValue implements KeyValue {
private static final class ParameterTypeImpl implements DynamicParameterizedType.ParameterType {
private final Class<?> returnedClass;
private final java.lang.reflect.Type returnedJavaType;
private final Annotation[] annotationsMethod;
private final String catalog;
private final String schema;
@ -1012,6 +1017,7 @@ public abstract class SimpleValue implements KeyValue {
private ParameterTypeImpl(
Class<?> returnedClass,
java.lang.reflect.Type returnedJavaType,
Annotation[] annotationsMethod,
String catalog,
String schema,
@ -1020,6 +1026,7 @@ public abstract class SimpleValue implements KeyValue {
String[] columns,
Long[] columnLengths) {
this.returnedClass = returnedClass;
this.returnedJavaType = returnedJavaType != null ? returnedJavaType : returnedClass;
this.annotationsMethod = annotationsMethod;
this.catalog = catalog;
this.schema = schema;
@ -1034,6 +1041,11 @@ public abstract class SimpleValue implements KeyValue {
return returnedClass;
}
@Override
public java.lang.reflect.Type getReturnedJavaType() {
return returnedJavaType;
}
@Override
public Annotation[] getAnnotationsMethod() {
return annotationsMethod;

View File

@ -6,7 +6,10 @@
*/
package org.hibernate.usertype;
import org.hibernate.Incubating;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Properties;
/**
@ -16,6 +19,7 @@ import java.util.Properties;
* instead of the key {@value PARAMETER_TYPE}.
*
* @author Janario Oliveira
* @author Yanming Zhou
*/
public interface DynamicParameterizedType extends ParameterizedType {
String PARAMETER_TYPE = "org.hibernate.type.ParameterType";
@ -33,6 +37,11 @@ public interface DynamicParameterizedType extends ParameterizedType {
Class<?> getReturnedClass();
@Incubating
default Type getReturnedJavaType() {
return getReturnedClass();
}
Annotation[] getAnnotationsMethod();
String getCatalog();

View File

@ -29,6 +29,7 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode;
@ -39,6 +40,8 @@ import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.type.CustomType;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;
import org.junit.jupiter.api.Test;
import java.util.Date;
@ -51,9 +54,10 @@ import static org.junit.jupiter.api.Assertions.*;
* @author Daniel Gredler
* @author Jan-Willem Gmelig Meyling
* @author Sayra Ranjha
* @author Yanming Zhou
*/
@DomainModel(
annotatedClasses = { AbstractEntity.class, Entity1.class, Entity2.class }
annotatedClasses = { AbstractEntity.class, Entity1.class, Entity2.class, Entity3.class }
)
@SessionFactory
@BootstrapServiceRegistry(
@ -107,6 +111,22 @@ public class DynamicParameterizedTypeTest {
});
}
@Test
public void testGetReturnedJavaType(SessionFactoryScope scope) {
scope.inTransaction(session -> {
EntityPersister persister = session.getEntityPersister("Entity3", new Entity3());
CustomType<?> mapping = (CustomType<?>) persister.findAttributeMapping("attributes").getSingleJdbcMapping();
UserType<?> userType = mapping.getUserType();
assertTrue(userType instanceof MyGenericType);
DynamicParameterizedType.ParameterType parameterType = ((MyGenericType) userType).getParameterType();
try {
assertEquals(parameterType.getReturnedJavaType(), Entity3.class.getDeclaredField("attributes").getGenericType());
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
});
}
public static class FunctionContributorImpl implements FunctionContributor {
@Override

View File

@ -0,0 +1,43 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.annotations.type.dynamicparameterized;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Entity;
import org.hibernate.annotations.Type;
import java.util.Map;
/**
* @author Yanming Zhou
*/
@Entity
@Access(AccessType.FIELD)
public class Entity3 extends AbstractEntity {
@Type( MyGenericType.class )
Map<String, String> attributes;
}

View File

@ -0,0 +1,103 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.annotations.type.dynamicparameterized;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
/**
* @author Yanming Zhou
*/
public class MyGenericType implements UserType<Object>, DynamicParameterizedType {
private ParameterType parameterType;
public ParameterType getParameterType() {
return parameterType;
}
@Override
public void setParameterValues(Properties params) {
parameterType = (ParameterType) params.get(PARAMETER_TYPE);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws SQLException {
st.setString( index, null );
}
@Override
public Object nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
return null;
}
@Override
public int getSqlType() {
return Types.VARCHAR;
}
@Override
public Class<Object> returnedClass() {
return Object.class;
}
@Override
public boolean equals(Object x, Object y) {
return ( x == null && y == null ) || ( x != null && x.equals( y ) );
}
@Override
public int hashCode(Object x) {
return x.hashCode();
}
@Override
public Object deepCopy(Object value) {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) {
return null;
}
@Override
public String assemble(Serializable cached, Object owner) {
return (String) cached;
}
}

View File

@ -42,6 +42,7 @@ import org.junit.Assert;
* makes it easier to verify that valid parameter values are being passed into {@link #setParameterValues(Properties)}.
*
* @author Daniel Gredler
* @author Yanming Zhou
*/
public class MyStringType implements UserType<String>, DynamicParameterizedType {
@ -85,6 +86,7 @@ public class MyStringType implements UserType<String>, DynamicParameterizedType
Assert.assertEquals( 1, parameterType.getColumns().length );
Assert.assertEquals( columnName, parameterType.getColumns()[0] );
Assert.assertEquals( String.class, parameterType.getReturnedClass() );
Assert.assertEquals( String.class, parameterType.getReturnedJavaType() );
Assert.assertEquals( tableName, parameterType.getTable() );
String value = tableName + "." + columnName;
@ -117,7 +119,7 @@ public class MyStringType implements UserType<String>, DynamicParameterizedType
@Override
public boolean equals(String x, String y) {
return ( x == null && y == null ) || ( x != null && y != null && x.equals( y ) );
return ( x == null && y == null ) || ( x != null && x.equals( y ) );
}
@Override