use of org.hibernate.type.descriptor.sql.SqlTypeDescriptor in project hibernate-orm by hibernate.
the class TypeOverrideTest method testNonStandardSqlTypeDescriptor.
@Test
public void testNonStandardSqlTypeDescriptor() {
// no override
SqlTypeDescriptor sqlTypeDescriptor = new IntegerTypeDescriptor() {
@Override
public boolean canBeRemapped() {
return false;
}
};
assertSame(sqlTypeDescriptor, remapSqlTypeDescriptor(sqlTypeDescriptor));
}
use of org.hibernate.type.descriptor.sql.SqlTypeDescriptor in project hibernate-orm by hibernate.
the class TypeOverrideTest method testDialectWithNonStandardSqlTypeDescriptor.
@Test
public void testDialectWithNonStandardSqlTypeDescriptor() {
assertNotSame(VarcharTypeDescriptor.INSTANCE, StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor());
final Dialect dialect = new H2DialectOverridePrefixedVarcharSqlTypeDesc();
final SqlTypeDescriptor remapped = remapSqlTypeDescriptor(dialect, StoredPrefixedStringType.PREFIXED_VARCHAR_TYPE_DESCRIPTOR);
assertSame(VarcharTypeDescriptor.INSTANCE, remapped);
}
use of org.hibernate.type.descriptor.sql.SqlTypeDescriptor in project hibernate-orm by hibernate.
the class AbstractSharedSessionContract method remapSqlTypeDescriptor.
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (!sqlTypeDescriptor.canBeRemapped()) {
return sqlTypeDescriptor;
}
final Dialect dialect = getJdbcServices().getJdbcEnvironment().getDialect();
final SqlTypeDescriptor remapped = dialect.remapSqlTypeDescriptor(sqlTypeDescriptor);
return remapped == null ? sqlTypeDescriptor : remapped;
}
use of org.hibernate.type.descriptor.sql.SqlTypeDescriptor in project hibernate-orm by hibernate.
the class SimpleValue method buildAttributeConverterTypeAdapter.
/**
* Build a Hibernate Type that incorporates the JPA AttributeConverter. AttributeConverter works totally in
* memory, meaning it converts between one Java representation (the entity attribute representation) and another
* (the value bound into JDBC statements or extracted from results). However, the Hibernate Type system operates
* at the lower level of actually dealing directly with those JDBC objects. So even though we have an
* AttributeConverter, we still need to "fill out" the rest of the BasicType data and bridge calls
* to bind/extract through the converter.
* <p/>
* Essentially the idea here is that an intermediate Java type needs to be used. Let's use an example as a means
* to illustrate... Consider an {@code AttributeConverter<Integer,String>}. This tells Hibernate that the domain
* model defines this attribute as an Integer value (the 'entityAttributeJavaType'), but that we need to treat the
* value as a String (the 'databaseColumnJavaType') when dealing with JDBC (aka, the database type is a
* VARCHAR/CHAR):<ul>
* <li>
* When binding values to PreparedStatements we need to convert the Integer value from the entity
* into a String and pass that String to setString. The conversion is handled by calling
* {@link AttributeConverter#convertToDatabaseColumn(Object)}
* </li>
* <li>
* When extracting values from ResultSets (or CallableStatement parameters) we need to handle the
* value via getString, and convert that returned String to an Integer. That conversion is handled
* by calling {@link AttributeConverter#convertToEntityAttribute(Object)}
* </li>
* </ul>
*
* @return The built AttributeConverter -> Type adapter
*
* @todo : ultimately I want to see attributeConverterJavaType and attributeConverterJdbcTypeCode specify-able separately
* then we can "play them against each other" in terms of determining proper typing
*
* @todo : see if we already have previously built a custom on-the-fly BasicType for this AttributeConverter; see note below about caching
*/
@SuppressWarnings("unchecked")
private Type buildAttributeConverterTypeAdapter() {
// todo : validate the number of columns present here?
final Class entityAttributeJavaType = attributeConverterDescriptor.getDomainType();
final Class databaseColumnJavaType = attributeConverterDescriptor.getJdbcType();
// resolve the JavaTypeDescriptor ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// For the JavaTypeDescriptor portion we simply resolve the "entity attribute representation" part of
// the AttributeConverter to resolve the corresponding descriptor.
final JavaTypeDescriptor entityAttributeJavaTypeDescriptor = JavaTypeDescriptorRegistry.INSTANCE.getDescriptor(entityAttributeJavaType);
// build the SqlTypeDescriptor adapter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Going back to the illustration, this should be a SqlTypeDescriptor that handles the Integer <-> String
// conversions. This is the more complicated piece. First we need to determine the JDBC type code
// corresponding to the AttributeConverter's declared "databaseColumnJavaType" (how we read that value out
// of ResultSets). See JdbcTypeJavaClassMappings for details. Again, given example, this should return
// VARCHAR/CHAR
int jdbcTypeCode = JdbcTypeJavaClassMappings.INSTANCE.determineJdbcTypeCodeForJavaClass(databaseColumnJavaType);
if (isLob()) {
if (LobTypeMappings.INSTANCE.hasCorrespondingLobCode(jdbcTypeCode)) {
jdbcTypeCode = LobTypeMappings.INSTANCE.getCorrespondingLobCode(jdbcTypeCode);
} else {
if (Serializable.class.isAssignableFrom(entityAttributeJavaType)) {
jdbcTypeCode = Types.BLOB;
} else {
throw new IllegalArgumentException(String.format(Locale.ROOT, "JDBC type-code [%s (%s)] not known to have a corresponding LOB equivalent, and Java type is not Serializable (to use BLOB)", jdbcTypeCode, JdbcTypeNameMapper.getTypeName(jdbcTypeCode)));
}
}
}
if (isNationalized()) {
jdbcTypeCode = NationalizedTypeMappings.INSTANCE.getCorrespondingNationalizedCode(jdbcTypeCode);
}
// find the standard SqlTypeDescriptor for that JDBC type code (allow itr to be remapped if needed!)
final SqlTypeDescriptor sqlTypeDescriptor = metadata.getMetadataBuildingOptions().getServiceRegistry().getService(JdbcServices.class).getJdbcEnvironment().getDialect().remapSqlTypeDescriptor(SqlTypeDescriptorRegistry.INSTANCE.getDescriptor(jdbcTypeCode));
// find the JavaTypeDescriptor representing the "intermediate database type representation". Back to the
// illustration, this should be the type descriptor for Strings
final JavaTypeDescriptor intermediateJavaTypeDescriptor = JavaTypeDescriptorRegistry.INSTANCE.getDescriptor(databaseColumnJavaType);
// and finally construct the adapter, which injects the AttributeConverter calls into the binding/extraction
// process...
final SqlTypeDescriptor sqlTypeDescriptorAdapter = new AttributeConverterSqlTypeDescriptorAdapter(attributeConverterDescriptor.getAttributeConverter(), sqlTypeDescriptor, intermediateJavaTypeDescriptor);
// todo : cache the AttributeConverterTypeAdapter in case that AttributeConverter is applied multiple times.
final String name = AttributeConverterTypeAdapter.NAME_PREFIX + attributeConverterDescriptor.getAttributeConverter().getClass().getName();
final String description = String.format("BasicType adapter for AttributeConverter<%s,%s>", entityAttributeJavaType.getSimpleName(), databaseColumnJavaType.getSimpleName());
return new AttributeConverterTypeAdapter(name, description, attributeConverterDescriptor.getAttributeConverter(), sqlTypeDescriptorAdapter, entityAttributeJavaType, databaseColumnJavaType, entityAttributeJavaTypeDescriptor);
}
Aggregations