We have the following classes
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // optional annotation as this is default
@DiscriminatorColumn(name = "apType", discriminatorType = DiscriminatorType.STRING, length = 255)
@DiscriminatorValue("AP")
public class ApplicationProcess {
}
And this
@Entity
@DiscriminatorValue("APS")
public class ApplicationProcessScheme extends ApplicationProcess {
}
Now I need to know at runtime if the ApplicationProcess
is of DiscriminatorValue
AP or APS
.
Since this is automatically handled by jpa, I have no way of getting this value.
We are calling a method that takes an ApplicationProcess
as parameter, and I want to avoid using instanceof
to check what type it is. Would be cooler if I could do something like
applicationProcess.getApType().equals("AP");
You can map your discriminator as a read-only property:
public class ApplicationProcess {
...
@Column(name = "apType", insertable = false, updatable = false)
private String apType;
}
I can imagine few cases where it might be helpful, but despite the reason why you need this, you could create on your abstract class method like
@Transient
public String getDiscriminatorValue(){
DiscriminatorValue val = this.getClass().getAnnotation( DiscriminatorValue.class );
return val == null ? null : val.value();
}
We are calling a method that takes an ApplicationProcess as parameter, and I want to avoid using instanceof to check what type it is. Would be cooler if I could do something like (...)
I don't think it would be cooler, this seems worse than calling instanceOf
to me: if for whatever reason you change the discriminator value, it would break your code.
If you need to check the type, use instanceOf
. A trick using the discriminator is not going to make things nicer, it would just make your code less robust.
You can use Formula Annotation. If you're using Hibernate, you can use the code below according to this link:
private String theApType;
@Formula("apType")
String getTheApType() {
return theApType;
}
Of course you would be able to use it in your queries.
I have used the following solution to get this value at runtime, assuming that you don't know beforehand what is the inheritance type:
SessionFactoryImpl sessionFactory = entityManager.getEntityManagerFactory().unwrap(SessionFactoryImpl.class);
EntityPersister entityPersister = sessionFactory.getEntityPersister( Task.class.getPackage().getName()+"."+param.getValue().get(0) );
int clazz_ = 0;
if(UnionSubclassEntityPersister.class.isInstance(entityPersister)) {
clazz_ = (Integer) ((UnionSubclassEntityPersister) entityPersister).getDiscriminatorValue();
} else if(JoinedSubclassEntityPersister.class.isInstance(entityPersister)) {
clazz_ = (Integer) ((JoinedSubclassEntityPersister) entityPersister).getDiscriminatorValue();
}
You should change the type of clazz_
according to your discriminatorType
annotations (Integer is the default for union and join strategies). This solution can be used for SINGLE_TABLE
too, if you add such case; or you can use the other solutions mentioned here.
I just came across this question and had to post an answer. IMO this is clear cut case for using Java reflection API
DiscriminatorValue annotation = ApplicationProcess.class.getAnnotation(DiscriminatorValue.class);
annotation.getValue().equals("AP");
来源:https://stackoverflow.com/questions/3005383/how-to-get-the-discriminatorvalue-at-run-time