HHH-18095 - transform column read/write fragments
This commit is contained in:
parent
61a00b1e6c
commit
086c7208cb
|
@ -91,6 +91,20 @@ public class AdditionalManagedResourcesImpl implements ManagedResources {
|
|||
private List<String> packageNames;
|
||||
private Collection<Binding<JaxbBindableMappingDescriptor>> xmlMappings;
|
||||
|
||||
public Builder(boolean validateMappings, boolean transformHbmMappings) {
|
||||
this( new MappingBinder.Options() {
|
||||
@Override
|
||||
public boolean validateMappings() {
|
||||
return validateMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transformHbmMappings() {
|
||||
return transformHbmMappings;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public Builder() {
|
||||
this( new MappingBinder.Options() {
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.annotations.CascadeType;
|
||||
import org.hibernate.annotations.ColumnTransformer;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
|
@ -73,6 +74,7 @@ import org.hibernate.boot.models.annotations.internal.CheckConstraintJpaAnnotati
|
|||
import org.hibernate.boot.models.annotations.internal.CollectionIdAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.CollectionTypeAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.ColumnJpaAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.ColumnTransformerAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.ConvertJpaAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.ConvertsJpaAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.DiscriminatorColumnJpaAnnotation;
|
||||
|
@ -197,19 +199,44 @@ public class XmlAnnotationHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
createColumnAnnotation( jaxbColumn, memberDetails, xmlDocumentContext );
|
||||
final ColumnJpaAnnotation columnAnnotationUsage = (ColumnJpaAnnotation) memberDetails.applyAnnotationUsage(
|
||||
COLUMN,
|
||||
xmlDocumentContext.getModelBuildingContext()
|
||||
);
|
||||
columnAnnotationUsage.apply( jaxbColumn, xmlDocumentContext );
|
||||
}
|
||||
|
||||
private static ColumnJpaAnnotation createColumnAnnotation(
|
||||
JaxbColumnImpl jaxbColumn,
|
||||
MutableAnnotationTarget target,
|
||||
XmlDocumentContext xmlDocumentContext) {
|
||||
final ColumnJpaAnnotation columnAnnotationUsage = (ColumnJpaAnnotation) target.applyAnnotationUsage(
|
||||
COLUMN,
|
||||
final ColumnJpaAnnotation usage = COLUMN.createUsage( xmlDocumentContext.getModelBuildingContext() );
|
||||
usage.apply( jaxbColumn, xmlDocumentContext );
|
||||
return usage;
|
||||
}
|
||||
|
||||
public static void applyColumnTransformation(
|
||||
JaxbColumnImpl jaxbColumn,
|
||||
MutableMemberDetails memberDetails,
|
||||
XmlDocumentContext xmlDocumentContext) {
|
||||
if ( StringHelper.isEmpty( jaxbColumn.getRead() )
|
||||
&& StringHelper.isEmpty( jaxbColumn.getWrite() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ColumnTransformerAnnotation annotationUsage = (ColumnTransformerAnnotation) memberDetails.applyAnnotationUsage(
|
||||
HibernateAnnotations.COLUMN_TRANSFORMER,
|
||||
xmlDocumentContext.getModelBuildingContext()
|
||||
);
|
||||
columnAnnotationUsage.apply( jaxbColumn, xmlDocumentContext );
|
||||
return columnAnnotationUsage;
|
||||
|
||||
annotationUsage.forColumn( jaxbColumn.getName() );
|
||||
|
||||
if ( StringHelper.isNotEmpty( jaxbColumn.getRead() ) ) {
|
||||
annotationUsage.read( jaxbColumn.getRead() );
|
||||
}
|
||||
if ( StringHelper.isNotEmpty( jaxbColumn.getWrite() ) ) {
|
||||
annotationUsage.write( jaxbColumn.getWrite() );
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyUserType(
|
||||
|
|
|
@ -70,6 +70,7 @@ public class BasicAttributeProcessing {
|
|||
xmlDocumentContext.getModelBuildingContext()
|
||||
);
|
||||
columnAnn.apply( jaxbBasic.getColumn(), xmlDocumentContext );
|
||||
XmlAnnotationHelper.applyColumnTransformation( jaxbBasic.getColumn(), memberDetails, xmlDocumentContext );
|
||||
}
|
||||
|
||||
XmlAnnotationHelper.applyConvert( jaxbBasic.getConvert(), memberDetails, xmlDocumentContext );
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.test.boot.models.xml.column.transform;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Item {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private double cost;
|
||||
|
||||
protected Item() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
||||
public Item(Integer id, String name, double cost) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public double getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public void setCost(double cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.test.boot.models.xml.column.transform;
|
||||
|
||||
import org.hibernate.annotations.ColumnTransformer;
|
||||
import org.hibernate.boot.internal.BootstrapContextImpl;
|
||||
import org.hibernate.boot.internal.MetadataBuilderImpl;
|
||||
import org.hibernate.boot.model.process.spi.ManagedResources;
|
||||
import org.hibernate.boot.model.source.internal.annotations.AdditionalManagedResourcesImpl;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.models.spi.ClassDetails;
|
||||
import org.hibernate.models.spi.FieldDetails;
|
||||
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hibernate.orm.test.boot.models.SourceModelTestHelper.createBuildingContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
public class ModelTests {
|
||||
@ServiceRegistry
|
||||
@Test
|
||||
void testMappingXml(ServiceRegistryScope scope) {
|
||||
final ManagedResources managedResources = new AdditionalManagedResourcesImpl.Builder()
|
||||
.addXmlMappings( "mappings/models/column/transform/mapping.xml" )
|
||||
.build();
|
||||
final StandardServiceRegistry serviceRegistry = scope.getRegistry();
|
||||
final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl(
|
||||
serviceRegistry,
|
||||
new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry )
|
||||
);
|
||||
|
||||
final SourceModelBuildingContext sourceModelBuildingContext = createBuildingContext(
|
||||
managedResources,
|
||||
false,
|
||||
new MetadataBuilderImpl.MetadataBuildingOptionsImpl( bootstrapContext.getServiceRegistry() ),
|
||||
bootstrapContext
|
||||
);
|
||||
|
||||
final ClassDetails classDetails = sourceModelBuildingContext.getClassDetailsRegistry().getClassDetails( Item.class.getName() );
|
||||
final FieldDetails costField = classDetails.findFieldByName( "cost" );
|
||||
final ColumnTransformer transformerAnn = costField.getAnnotationUsage( ColumnTransformer.class, sourceModelBuildingContext );
|
||||
assertThat( transformerAnn ).isNotNull();
|
||||
assertThat( transformerAnn.read() ).isEqualTo( "cost / 100.00" );
|
||||
assertThat( transformerAnn.write() ).isEqualTo( "? * 100.00" );
|
||||
}
|
||||
|
||||
@ServiceRegistry
|
||||
@Test
|
||||
void testHbmXml(ServiceRegistryScope scope) {
|
||||
final ManagedResources managedResources = new AdditionalManagedResourcesImpl.Builder( true, true )
|
||||
.addXmlMappings( "mappings/models/column/transform/hbm.xml" )
|
||||
.build();
|
||||
final StandardServiceRegistry serviceRegistry = scope.getRegistry();
|
||||
final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl(
|
||||
serviceRegistry,
|
||||
new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry )
|
||||
);
|
||||
|
||||
final SourceModelBuildingContext sourceModelBuildingContext = createBuildingContext(
|
||||
managedResources,
|
||||
false,
|
||||
new MetadataBuilderImpl.MetadataBuildingOptionsImpl( bootstrapContext.getServiceRegistry() ),
|
||||
bootstrapContext
|
||||
);
|
||||
|
||||
final ClassDetails classDetails = sourceModelBuildingContext.getClassDetailsRegistry().getClassDetails( Item.class.getName() );
|
||||
final FieldDetails costField = classDetails.findFieldByName( "cost" );
|
||||
final ColumnTransformer transformerAnn = costField.getAnnotationUsage( ColumnTransformer.class, sourceModelBuildingContext );
|
||||
assertThat( transformerAnn ).isNotNull();
|
||||
assertThat( transformerAnn.read() ).isEqualTo( "cost / 100.00" );
|
||||
assertThat( transformerAnn.write() ).isEqualTo( "? * 100.00" );
|
||||
}
|
||||
|
||||
@ServiceRegistry
|
||||
@DomainModel(xmlMappings = "mappings/models/column/transform/mapping.xml")
|
||||
@Test
|
||||
void testMappingModel(DomainModelScope domainModelScope) {
|
||||
domainModelScope.withHierarchy( Item.class, (rootClass) -> {
|
||||
final Property costProperty = rootClass.getProperty( "cost" );
|
||||
assertThat( costProperty.getColumns() ).hasSize( 1 );
|
||||
final Column column = costProperty.getColumns().get( 0 );
|
||||
assertThat( column.getCustomRead() ).isEqualTo( "cost / 100.00" );
|
||||
assertThat( column.getCustomWrite() ).isEqualTo( "? * 100.00" );
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
-->
|
||||
<hibernate-mapping
|
||||
xmlns="http://www.hibernate.org/xsd/orm/hbm"
|
||||
default-access="field"
|
||||
package="org.hibernate.orm.test.boot.models.xml.column.transform">
|
||||
<class name="Item" >
|
||||
<id name="id"/>
|
||||
<property name="name"/>
|
||||
<property name="cost">
|
||||
<column name="cost" read="cost / 100.00" write="? * 100.00"/>
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,25 @@
|
|||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
~ Copyright: Red Hat Inc. and Hibernate Authors
|
||||
-->
|
||||
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
version="7.0">
|
||||
<package>org.hibernate.orm.test.boot.models.xml.column.transform</package>
|
||||
<entity class="Item" metadata-complete="true" access="FIELD">
|
||||
<table name="items"/>
|
||||
<attributes>
|
||||
<id name="id"/>
|
||||
<basic name="name"/>
|
||||
<basic name="cost">
|
||||
<column>
|
||||
<read>cost / 100.00</read>
|
||||
<write>? * 100.00</write>
|
||||
</column>
|
||||
<jdbc-type-code>2</jdbc-type-code>
|
||||
</basic>
|
||||
</attributes>
|
||||
</entity>
|
||||
</entity-mappings>
|
Loading…
Reference in New Issue