HHH-9158 - cascade-persist in orm.xml does not apply to annotation-based relationships

This commit is contained in:
Gary LosHuertos 2014-05-02 17:33:07 -04:00 committed by Vlad Mihalcea
parent abb3590d33
commit c4010d0af0
5 changed files with 125 additions and 3 deletions

View File

@ -203,11 +203,11 @@ public interface AvailableSettings {
/**
* Used to define how the current thread context {@link ClassLoader} must be used
* for class lookup.
*
*
* @see TcclLookupPrecedence
*/
String TC_CLASSLOADER = "hibernate.classLoader.tccl_lookup_precedence";
/**
* Names the {@link ClassLoader} used to load user application classes.
* @since 4.0
@ -1494,7 +1494,7 @@ public interface AvailableSettings {
* Names the {@link org.hibernate.loader.BatchFetchStyle} to use. Can specify either the
* {@link org.hibernate.loader.BatchFetchStyle} name (insensitively), or a
* {@link org.hibernate.loader.BatchFetchStyle} instance.
*
*
* {@code LEGACY} is the default value.
*/
String BATCH_FETCH_STYLE = "hibernate.batch_fetch_style";

View File

@ -91,6 +91,7 @@ public class JPAMetadataProvider implements MetadataProvider {
defaults.put( "schema", xmlDefaults.getSchema() );
defaults.put( "catalog", xmlDefaults.getCatalog() );
defaults.put( "delimited-identifier", xmlDefaults.getDelimitedIdentifier() );
defaults.put( "cascade-persist", xmlDefaults.getCascadePersist() );
List<Class> entityListeners = new ArrayList<Class>();
for ( String className : xmlContext.getDefaultEntityListeners() ) {
try {

View File

@ -13,6 +13,7 @@ import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -779,6 +780,52 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
private Annotation overridesDefaultCascadePersist(Annotation annotation, XMLContext.Default defaults) {
if ( Boolean.TRUE.equals( defaults.getCascadePersist() ) ) {
final Class<? extends Annotation> annotationType = annotation.annotationType();
if ( annotationType == ManyToOne.class ) {
ManyToOne manyToOne = (ManyToOne) annotation;
List<CascadeType> cascades = new ArrayList<>( Arrays.asList( manyToOne.cascade() ) );
if ( !cascades.contains( CascadeType.ALL ) && !cascades.contains( CascadeType.PERSIST ) ) {
cascades.add( CascadeType.PERSIST );
}
else {
return annotation;
}
AnnotationDescriptor ad = new AnnotationDescriptor( annotationType );
ad.setValue( "cascade", cascades.toArray( new CascadeType[] {} ) );
ad.setValue( "targetEntity", manyToOne.targetEntity() );
ad.setValue( "fetch", manyToOne.fetch() );
ad.setValue( "optional", manyToOne.optional() );
return AnnotationFactory.create( ad );
}
else if ( annotationType == OneToOne.class ) {
OneToOne oneToOne = (OneToOne) annotation;
List<CascadeType> cascades = new ArrayList<>( Arrays.asList( oneToOne.cascade() ) );
if ( !cascades.contains( CascadeType.ALL ) && !cascades.contains( CascadeType.PERSIST ) ) {
cascades.add( CascadeType.PERSIST );
}
else {
return annotation;
}
AnnotationDescriptor ad = new AnnotationDescriptor( annotationType );
ad.setValue( "cascade", cascades.toArray( new CascadeType[] {} ) );
ad.setValue( "targetEntity", oneToOne.targetEntity() );
ad.setValue( "fetch", oneToOne.fetch() );
ad.setValue( "optional", oneToOne.optional() );
ad.setValue( "mappedBy", oneToOne.mappedBy() );
ad.setValue( "orphanRemoval", oneToOne.orphanRemoval() );
return AnnotationFactory.create( ad );
}
}
return annotation;
}
private void getJoinTable(List<Annotation> annotationList, Element tree, XMLContext.Default defaults) {
addIfNotNull( annotationList, buildJoinTable( tree, defaults ) );
}
@ -857,6 +904,7 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) {
Annotation annotation = getPhysicalAnnotation( annotationType );
if ( annotation != null ) {
annotation = overridesDefaultCascadePersist( annotation, defaults );
annotationList.add( annotation );
annotation = overridesDefaultsInJoinTable( annotation, defaults );
addIfNotNull( annotationList, annotation );

View File

@ -0,0 +1,72 @@
/*
* 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.jpa.test.mapping;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
public class DefaultCascadeTest extends BaseEntityManagerFunctionalTestCase {
@Test
public void testCascadePersist() {
doInJPA( this::entityManagerFactory, entityManager -> {
Parent parent = new Parent();
Child child = new Child();
child.parent = parent;
entityManager.persist( child );
} );
}
@Override
public String[] getEjb3DD() {
return new String[] {
"org/hibernate/jpa/test/mapping/orm.xml"
};
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Parent.class,
Child.class
};
}
@Entity
@Table(name = "Parent")
public static class Parent {
@Id
@GeneratedValue
private Integer id;
}
@Entity
@Table(name = "Child")
public static class Child {
@Id
@GeneratedValue
private Integer id;
@ManyToOne
private Parent parent;
}
}

View File

@ -9,6 +9,7 @@
<persistence-unit-metadata>
<persistence-unit-defaults>
<delimited-identifiers/>
<cascade-persist/>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>