HHH-15935 add discriminatorType to @DiscriminatorFormula

This commit is contained in:
Gavin 2022-12-25 21:20:28 +01:00 committed by Gavin King
parent a4191c9e11
commit 491b1bc06f
7 changed files with 65 additions and 18 deletions

View File

@ -6,9 +6,12 @@
*/
package org.hibernate.annotations;
import jakarta.persistence.DiscriminatorType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static jakarta.persistence.DiscriminatorType.STRING;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -18,6 +21,40 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* the hierarchy.
* <p>
* Used in place of the JPA {@link jakarta.persistence.DiscriminatorColumn}.
* <p>
* For example, we might declare a supertype as follows:
* <pre>{@code
* @Entity
* @DiscriminatorFormula(discriminatorType = INTEGER,
* value = "case when value1 is not null then 1 when value2 is not null then 2 end")
* public abstract class AbstractChild {
* @Id
* @GeneratedValue
* Integer id;
* ...
* }
* }</pre>
* and then each concrete subclass must specify a matching discriminator value:
* <pre>{@code
* @Entity
* @DiscriminatorValue("1")
* public class ConcreteChild1 extends AbstractChild {
* @Basic(optional = false)
* @Column(name = "VALUE1")
* String value;
* ...
* }
* }</pre>
* <pre>{@code
* @Entity
* @DiscriminatorValue("2")
* public class ConcreteChild2 extends AbstractChild {
* @Basic(optional = false)
* @Column(name = "VALUE2")
* String value;
* ...
* }
* }</pre>
*
* @see Formula
* @see DialectOverride.DiscriminatorFormula
@ -25,11 +62,19 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
@Target({TYPE})
@Target(TYPE)
@Retention(RUNTIME)
public @interface DiscriminatorFormula {
/**
* The formula string.
*/
String value();
/**
* The type of value returned by the formula.
* <p>
* This is required, unless the {@linkplain #value()
* expression} is of type {@code varchar} or similar.
*/
DiscriminatorType discriminatorType() default STRING;
}

View File

@ -43,18 +43,26 @@ public class AnnotatedDiscriminatorColumn extends AnnotatedColumn {
}
public static AnnotatedDiscriminatorColumn buildDiscriminatorColumn(
DiscriminatorType type,
DiscriminatorColumn discriminatorColumn,
DiscriminatorFormula discriminatorFormula,
MetadataBuildingContext context) {
final AnnotatedColumns parent = new AnnotatedColumns();
parent.setBuildingContext( context );
final AnnotatedDiscriminatorColumn column = new AnnotatedDiscriminatorColumn();
final DiscriminatorType discriminatorType;
if ( discriminatorFormula != null ) {
final DiscriminatorType type = discriminatorFormula.discriminatorType();
if ( type == DiscriminatorType.STRING ) {
discriminatorType = discriminatorColumn == null ? type : discriminatorColumn.discriminatorType();
}
else {
discriminatorType = type;
}
column.setImplicit( false );
column.setFormula( discriminatorFormula.value() );
}
else if ( discriminatorColumn != null ) {
discriminatorType = discriminatorColumn.discriminatorType();
column.setImplicit( false );
if ( !discriminatorColumn.columnDefinition().isEmpty() ) {
column.setSqlType( discriminatorColumn.columnDefinition() );
@ -65,9 +73,10 @@ public class AnnotatedDiscriminatorColumn extends AnnotatedColumn {
column.setNullable( false );
}
else {
discriminatorType = DiscriminatorType.STRING;
column.setImplicit( true );
}
setDiscriminatorType( type, discriminatorColumn, column );
setDiscriminatorType( discriminatorType, discriminatorColumn, column );
column.setParent( parent );
column.bind();
return column;

View File

@ -779,16 +779,13 @@ public class EntityBinder {
private AnnotatedDiscriminatorColumn processSingleTableDiscriminatorProperties(InheritanceState inheritanceState) {
final DiscriminatorColumn discriminatorColumn = annotatedClass.getAnnotation( DiscriminatorColumn.class );
final DiscriminatorType discriminatorType = discriminatorColumn != null
? discriminatorColumn.discriminatorType()
: DiscriminatorType.STRING;
final DiscriminatorFormula discriminatorFormula =
getOverridableAnnotation( annotatedClass, DiscriminatorFormula.class, context );
final boolean isRoot = !inheritanceState.hasParents();
final AnnotatedDiscriminatorColumn discriminator = isRoot
? buildDiscriminatorColumn( discriminatorType, discriminatorColumn, discriminatorFormula, context )
? buildDiscriminatorColumn( discriminatorColumn, discriminatorFormula, context )
: null;
if ( discriminatorColumn != null && !isRoot ) {
//TODO: shouldn't this be an error?!
@ -835,10 +832,7 @@ public class EntityBinder {
}
if ( generateDiscriminatorColumn ) {
final DiscriminatorType discriminatorType = discriminatorColumn != null
? discriminatorColumn.discriminatorType()
: DiscriminatorType.STRING;
return buildDiscriminatorColumn( discriminatorType, discriminatorColumn, null, context );
return buildDiscriminatorColumn( discriminatorColumn, null, context );
}
}
else {

View File

@ -3,13 +3,14 @@ package org.hibernate.orm.test.annotations.sharedfk;
import jakarta.persistence.*;
import org.hibernate.annotations.DiscriminatorFormula;
import static jakarta.persistence.DiscriminatorType.INTEGER;
@Entity
@Table(name = " INHERITANCE_TAB")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Access(AccessType.FIELD)
//@DiscriminatorColumn(name = "DISC")
@DiscriminatorFormula("case when value1 is not null then 1 when value2 is not null then 2 end")
public class AbstractChild {
@DiscriminatorFormula(discriminatorType = INTEGER,
value = "case when value1 is not null then 1 when value2 is not null then 2 end")
public abstract class AbstractChild {
@Id
@GeneratedValue
@Column(name = "ID")

View File

@ -8,7 +8,6 @@ import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
@Entity
@Access(AccessType.FIELD)
@DiscriminatorValue("1")
public class ConcreteChild1 extends AbstractChild {
@Basic(optional = false)

View File

@ -3,7 +3,6 @@ package org.hibernate.orm.test.annotations.sharedfk;
import jakarta.persistence.*;
@Entity
@Access(AccessType.FIELD)
@DiscriminatorValue("2")
public class ConcreteChild2 extends AbstractChild {
@Basic(optional = false)

View File

@ -19,8 +19,8 @@ public class Parent {
@OneToMany( fetch= FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
@OrderColumn(name = "ORDER_C")
List<ConcreteChild1> child1s = new LinkedList<>();
@OneToMany( fetch= FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
@OrderColumn(name = "ORDER_C")