HHH-18072 - Transform hbm.xml not-found
This commit is contained in:
parent
9f58dc1b98
commit
6db0987a2c
|
@ -7,12 +7,14 @@
|
|||
package org.hibernate.boot.jaxb.hbm.transform;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
import org.hibernate.annotations.PolymorphismType;
|
||||
import org.hibernate.boot.MappingException;
|
||||
|
@ -155,10 +157,14 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.xml.bind.JAXBContext;
|
||||
import jakarta.xml.bind.JAXBElement;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
import jakarta.xml.bind.Marshaller;
|
||||
|
||||
import static org.hibernate.boot.jaxb.hbm.transform.HbmTransformationLogging.TRANSFORMATION_LOGGER;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
|
@ -234,9 +240,26 @@ public class HbmXmlTransformer {
|
|||
transferFetchProfiles();
|
||||
transferDatabaseObjects();
|
||||
|
||||
if ( TRANSFORMATION_LOGGER.isDebugEnabled() ) {
|
||||
dumpTransformed( origin, ormRoot );
|
||||
}
|
||||
return ormRoot;
|
||||
}
|
||||
|
||||
private static void dumpTransformed(Origin origin, JaxbEntityMappingsImpl ormRoot) {
|
||||
try {
|
||||
JAXBContext ctx = JAXBContext.newInstance( JaxbEntityMappingsImpl.class );
|
||||
Marshaller marshaller = ctx.createMarshaller();
|
||||
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true );
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
marshaller.marshal( ormRoot, stringWriter );
|
||||
TRANSFORMATION_LOGGER.debugf( "Transformed hbm.xml (%s):\n%s", origin, stringWriter.toString() );
|
||||
}
|
||||
catch (JAXBException e) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void transfer(Supplier<T> source, Consumer<T> target) {
|
||||
final T value = source.get();
|
||||
if ( value != null ) {
|
||||
|
@ -1479,15 +1502,18 @@ public class HbmXmlTransformer {
|
|||
}
|
||||
|
||||
private JaxbManyToOneImpl transformManyToOne(final JaxbHbmManyToOneType hbmNode) {
|
||||
if ( hbmNode.getNotFound() != null ) {
|
||||
handleUnsupported( "`not-found` not supported for transformation" );
|
||||
}
|
||||
|
||||
final JaxbManyToOneImpl m2o = new JaxbManyToOneImpl();
|
||||
m2o.setAttributeAccessor( hbmNode.getAccess() );
|
||||
m2o.setCascade( convertCascadeType( hbmNode.getCascade() ) );
|
||||
m2o.setForeignKeys( new JaxbForeignKeyImpl() );
|
||||
m2o.getForeignKeys().setName( hbmNode.getForeignKey() );
|
||||
if ( hbmNode.getForeignKey() != null ) {
|
||||
m2o.setForeignKeys( new JaxbForeignKeyImpl() );
|
||||
if ( "none".equalsIgnoreCase( hbmNode.getForeignKey() ) ) {
|
||||
m2o.getForeignKeys().setConstraintMode( ConstraintMode.NO_CONSTRAINT );
|
||||
}
|
||||
else {
|
||||
m2o.getForeignKeys().setName( hbmNode.getForeignKey() );
|
||||
}
|
||||
}
|
||||
|
||||
transferColumnsAndFormulas(
|
||||
new ColumnAndFormulaSource() {
|
||||
|
@ -1543,9 +1569,21 @@ public class HbmXmlTransformer {
|
|||
m2o.setTargetEntity( hbmNode.getClazz() );
|
||||
}
|
||||
transferFetchable( hbmNode.getLazy(), hbmNode.getFetch(), hbmNode.getOuterJoin(), null, m2o );
|
||||
|
||||
if ( hbmNode.getNotFound() != null ) {
|
||||
m2o.setNotFound( interpretNotFoundAction( hbmNode.getNotFound() ) );
|
||||
}
|
||||
|
||||
return m2o;
|
||||
}
|
||||
|
||||
private NotFoundAction interpretNotFoundAction(JaxbHbmNotFoundEnum hbmNotFound) {
|
||||
return switch ( hbmNotFound ) {
|
||||
case EXCEPTION -> NotFoundAction.EXCEPTION;
|
||||
case IGNORE -> NotFoundAction.IGNORE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private JaxbAnyMappingImpl transformAnyAttribute(JaxbHbmAnyAssociationType source) {
|
||||
final JaxbAnyMappingImpl target = new JaxbAnyMappingImpl();
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.jboss.logging.Logger;
|
|||
*/
|
||||
@Internal
|
||||
public interface XmlProcessLogging {
|
||||
String NAME = "org.hibernate.models.xml";
|
||||
String NAME = "org.hibernate.orm.models.xml";
|
||||
|
||||
Logger XML_PROCESS_LOGGER = Logger.getLogger( NAME );
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.models.ModelsException;
|
||||
import org.hibernate.models.internal.ClassTypeDetailsImpl;
|
||||
import org.hibernate.models.internal.ModelsClassLogging;
|
||||
import org.hibernate.models.internal.RenderingCollectorImpl;
|
||||
import org.hibernate.models.internal.dynamic.DynamicClassDetails;
|
||||
import org.hibernate.models.internal.dynamic.DynamicFieldDetails;
|
||||
import org.hibernate.models.spi.AnnotationUsage;
|
||||
|
@ -61,6 +62,7 @@ import jakarta.persistence.Cacheable;
|
|||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
import static org.hibernate.boot.models.xml.XmlProcessLogging.XML_PROCESS_LOGGER;
|
||||
import static org.hibernate.internal.util.NullnessHelper.coalesce;
|
||||
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
|
@ -571,6 +573,18 @@ public class ManagedTypeProcessor {
|
|||
classDetails,
|
||||
xmlDocumentContext
|
||||
);
|
||||
|
||||
renderClass( classDetails, xmlDocumentContext );
|
||||
}
|
||||
|
||||
private static void renderClass(MutableClassDetails classDetails, XmlDocumentContext xmlDocumentContext) {
|
||||
if ( !XML_PROCESS_LOGGER.isDebugEnabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
|
||||
classDetails.render( renderingCollector );
|
||||
XML_PROCESS_LOGGER.debugf( "Class annotations from XML for %s:\n%s", classDetails.getName(), renderingCollector.toString() );
|
||||
}
|
||||
|
||||
private static void applyAccessAnnotation(
|
||||
|
@ -826,6 +840,8 @@ public class ManagedTypeProcessor {
|
|||
}
|
||||
|
||||
processEntityOrMappedSuperclass( jaxbMappedSuperclass, classDetails, xmlDocumentContext );
|
||||
|
||||
renderClass( classDetails, xmlDocumentContext );
|
||||
}
|
||||
|
||||
public static void processOverrideMappedSuperclass(List<XmlProcessingResult.OverrideTuple<JaxbMappedSuperclassImpl>> mappedSuperclassesOverrides) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.hbm.notfound;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Employee2 {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public Employee2() {
|
||||
}
|
||||
|
||||
public Employee2(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.hbm.notfound;
|
||||
|
||||
import org.hibernate.cfg.MappingSettings;
|
||||
import org.hibernate.orm.test.unconstrained.UnconstrainedTest;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @see UnconstrainedTest
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
@ServiceRegistry(settings = @Setting(name= MappingSettings.TRANSFORM_HBM_XML, value = "true"))
|
||||
@DomainModel(xmlMappings = "mappings/models/hbm/notfound/Person2.hbm.xml")
|
||||
@SessionFactory
|
||||
public class HbmNotFoundTransformationTests {
|
||||
@Test
|
||||
void testNotFoundTransformation(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final Employee2 employee = new Employee2( 1, "employee" );
|
||||
final Person2 person = new Person2( 1, "person", employee );
|
||||
session.persist( employee );
|
||||
session.persist( person );
|
||||
} );
|
||||
scope.inTransaction( (session) -> session.createMutationQuery( "delete Employee2" ).executeUpdate() );
|
||||
scope.inTransaction( (session) -> {
|
||||
final Person2 loaded = session.find( Person2.class, 1 );
|
||||
assertThat( loaded ).isNotNull();
|
||||
assertThat( loaded.getEmployee() ).isNull();
|
||||
} );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.createMutationQuery( "delete Person2" ).executeUpdate();
|
||||
session.createMutationQuery( "delete Employee2" ).executeUpdate();
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.hbm.notfound;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Person2 {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private Employee2 employee;
|
||||
|
||||
public Person2() {
|
||||
}
|
||||
|
||||
public Person2(Integer id, String name, Employee2 employee) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.employee = employee;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Employee2 getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
public void setEmployee(Employee2 employee) {
|
||||
this.employee = employee;
|
||||
}
|
||||
}
|
|
@ -55,6 +55,11 @@ logger.sql-result-ast.name=org.hibernate.orm.sql.results.graph.AST
|
|||
logger.sqm-tree.name=org.hibernate.orm.query.sqm.ast
|
||||
#logger.sqm-tree.level=debug
|
||||
|
||||
logger.hbm-xml.name=org.hibernate.orm.boot.jaxb.hbm-transform
|
||||
#logger.hbm-xml.level=debug
|
||||
|
||||
logger.xml.name=org.hibernate.orm.models.xml
|
||||
#logger.xml.level=debug
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ 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>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping
|
||||
package="org.hibernate.orm.test.boot.models.hbm.notfound"
|
||||
default-access="field">
|
||||
|
||||
<class name="Person2">
|
||||
<id name="id"/>
|
||||
<property name="name"/>
|
||||
<many-to-one name="employee" column="employee_fk" not-found="ignore" cascade="all"/>
|
||||
</class>
|
||||
|
||||
<class name="Employee2">
|
||||
<id name="id"/>
|
||||
<property name="name"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
Loading…
Reference in New Issue