HHH-6911 - Write DiscriminatorValue to DiscriminatorColumn when combined

with InheritanceType#JOINED

Conflicts:
	hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
This commit is contained in:
Steve Ebersole 2013-12-16 12:34:55 -05:00 committed by Brett Meyer
parent b01abeadef
commit d847a171eb
5 changed files with 172 additions and 6 deletions

View File

@ -829,7 +829,11 @@ public final class AnnotationBinder {
final DiscriminatorColumn discriminatorColumnAnnotation = clazzToProcess.getAnnotation( DiscriminatorColumn.class ); final DiscriminatorColumn discriminatorColumnAnnotation = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
if ( !inheritanceState.hasParents() ) { if ( !inheritanceState.hasParents() ) {
if ( discriminatorColumnAnnotation != null || mappings.useImplicitDiscriminatorColumnForJoinedInheritance() ) { // we want to process the discriminator column if either:
// 1) There is an explicit DiscriminatorColumn annotation && we are not told to ignore them
// 2) There is not an explicit DiscriminatorColumn annotation && we are told to create them implicitly
if ( ( discriminatorColumnAnnotation != null && !mappings.ignoreExplicitDiscriminatorColumnForJoinedInheritance() )
|| ( discriminatorColumnAnnotation == null && mappings.useImplicitDiscriminatorColumnForJoinedInheritance() ) ) {
final DiscriminatorType discriminatorType = discriminatorColumnAnnotation != null final DiscriminatorType discriminatorType = discriminatorColumnAnnotation != null
? discriminatorColumnAnnotation.discriminatorType() ? discriminatorColumnAnnotation.discriminatorType()
: DiscriminatorType.STRING; : DiscriminatorType.STRING;

View File

@ -617,11 +617,28 @@ public interface AvailableSettings {
* discriminator metadata means to follow the legacy behavior *unless* this setting is enabled. With this setting * discriminator metadata means to follow the legacy behavior *unless* this setting is enabled. With this setting
* enabled, Hibernate will interpret the absence of discriminator metadata as an indication to use the JPA * enabled, Hibernate will interpret the absence of discriminator metadata as an indication to use the JPA
* defined defaults for these absent annotations. * defined defaults for these absent annotations.
* <p/>
* See Hibernate Jira issue HHH-6911 for additional background info.
* *
* See Hibernate Jira issue HHH-6911 for additional background info, * @see #IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/ */
public static final String IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.implicit_for_joined"; public static final String IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.implicit_for_joined";
/**
* The legacy behavior of Hibernate is to not use discriminators for joined inheritance (Hibernate does not need
* the discriminator...). However, some JPA providers do need the discriminator for handling joined inheritance.
* In the interest of portability this capability has been added to Hibernate too.
* <p/>
* Existing applications rely (implicitly or explicitly) on Hibernate ignoring any DiscriminatorColumn declarations
* on joined inheritance hierarchies. This setting allows these applications to maintain the legacy behavior
* of DiscriminatorColumn annotations being ignored when paired with joined inheritance.
* <p/>
* See Hibernate Jira issue HHH-6911 for additional background info.
*
* @see #IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/
public static final String IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.ignore_explicit_for_joined";
public static final String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans"; public static final String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
public static final String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy"; public static final String HQL_BULK_ID_STRATEGY = "hibernate.hql.bulk_id_strategy";

View File

@ -3185,6 +3185,19 @@ public class Configuration implements Serializable {
} }
private Boolean ignoreExplicitDiscriminatorColumnForJoinedInheritance;
@Override
public boolean ignoreExplicitDiscriminatorColumnForJoinedInheritance() {
if ( ignoreExplicitDiscriminatorColumnForJoinedInheritance == null ) {
final String booleanName = getConfigurationProperties()
.getProperty( AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS );
ignoreExplicitDiscriminatorColumnForJoinedInheritance = Boolean.valueOf( booleanName );
}
return ignoreExplicitDiscriminatorColumnForJoinedInheritance;
}
private Boolean useNationalizedCharacterData; private Boolean useNationalizedCharacterData;
@Override @Override

View File

@ -748,16 +748,26 @@ public interface Mappings {
public boolean useNewGeneratorMappings(); public boolean useNewGeneratorMappings();
/** /**
* Should we handle discriminators for joined inheritance per legacy Hibernate rules, or * Should we handle absent DiscriminatorColumn mappings for joined inheritance by implicitly mapping a
* Should we use the new generator strategy mappings. This is controlled by the * discriminator column?
* {@link AvailableSettings#USE_NEW_ID_GENERATOR_MAPPINGS} setting.
* *
* @return True if the new generators should be used, false otherwise. * @return {@code true} indicates we should infer DiscriminatorColumn implicitly (aka, map to a discriminator
* column even without a DiscriminatorColumn annotation); {@code false} (the default) indicates that we should not.
* *
* @see AvailableSettings#IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS * @see AvailableSettings#IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/ */
public boolean useImplicitDiscriminatorColumnForJoinedInheritance(); public boolean useImplicitDiscriminatorColumnForJoinedInheritance();
/**
* Should we ignore explicit DiscriminatorColumn annotations when combined with joined inheritance?
*
* @return {@code true} indicates we should ignore explicit DiscriminatorColumn annotations; {@code false} (the
* default) indicates we should not ignore them
*
* @see AvailableSettings#IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/
public boolean ignoreExplicitDiscriminatorColumnForJoinedInheritance();
/** /**
* Should we use nationalized variants of character data by default? This is controlled by the * Should we use nationalized variants of character data by default? This is controlled by the
* {@link AvailableSettings#USE_NATIONALIZED_CHARACTER_DATA} setting. * {@link AvailableSettings#USE_NATIONALIZED_CHARACTER_DATA} setting.

View File

@ -0,0 +1,122 @@
package org.hibernate.test.joinedsubclass;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-6911" )
public class JoinedSubclassWithIgnoredExplicitDiscriminatorTest extends BaseCoreFunctionalTestCase {
@Entity( name = "Animal" )
@Table( name = "animal" )
@Inheritance( strategy = InheritanceType.JOINED )
@DiscriminatorColumn( name = "type", discriminatorType = DiscriminatorType.STRING )
@DiscriminatorValue( value = "???animal???" )
public static abstract class Animal {
@Id
public Integer id;
protected Animal() {
}
protected Animal(Integer id) {
this.id = id;
}
}
@Entity( name = "Cat" )
@DiscriminatorValue( value = "cat" )
public static class Cat extends Animal {
public Cat() {
super();
}
public Cat(Integer id) {
super( id );
}
}
@Entity( name = "Dog" )
@DiscriminatorValue( value = "dog" )
public static class Dog extends Animal {
public Dog() {
super();
}
public Dog(Integer id) {
super( id );
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Animal.class, Cat.class, Dog.class };
}
@Override
protected void configure(Configuration configuration) {
super.configure( configuration );
configuration.setProperty( AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, "true" );
}
@Test
public void metadataAssertions() {
EntityPersister p = sessionFactory().getEntityPersister( Dog.class.getName() );
assertNotNull( p );
final JoinedSubclassEntityPersister dogPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
assertEquals( "integer", dogPersister.getDiscriminatorType().getName() );
assertEquals( "clazz_", dogPersister.getDiscriminatorColumnName() );
assertTrue( Integer.class.isInstance( dogPersister.getDiscriminatorValue() ) );
p = sessionFactory().getEntityPersister( Cat.class.getName() );
assertNotNull( p );
final JoinedSubclassEntityPersister catPersister = assertTyping( JoinedSubclassEntityPersister.class, p );
assertEquals( "integer", catPersister.getDiscriminatorType().getName() );
assertEquals( "clazz_", catPersister.getDiscriminatorColumnName() );
assertTrue( Integer.class.isInstance( catPersister.getDiscriminatorValue() ) );
}
@Test
public void basicUsageTest() {
Session session = openSession();
session.beginTransaction();
session.save( new Cat( 1 ) );
session.save( new Dog( 2 ) );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
session.createQuery( "from Animal" ).list();
Cat cat = (Cat) session.get( Cat.class, 1 );
assertNotNull( cat );
session.delete( cat );
Dog dog = (Dog) session.get( Dog.class, 2 );
assertNotNull( dog );
session.delete( dog );
session.getTransaction().commit();
session.close();
}
}