我有一个应用程序,该应用程序使用传入的消息,解析消息中存在的数据,然后将规则应用于该数据。在“规则”实体上,有一列可以区分规则的类型。
我想将规则的结果保留为单独的表或子类,这取决于处理它们的规则类型。
我目前正在通过创建父@MappedSuperclass
(抽象)BaseResult对象以及扩展BaseResult的AppleResult和OrangeResult @Enitiy
解决此问题。
我的问题是,考虑到下面的语句,如何在模型中改进/注释我的对象,以便在访问/持久化该实例时不必为每个实例执行一次instanceof检查?现在,这是我为避免“基本结果不存在” SQL语法异常而必须做的事情:
public void save(BaseResult baseResult) {
if (baseResult instanceof AppleResult) {
jpaApi.em().merge((AppleResult) baseResult);
} else if (baseResult instanceof OrangeResult) {
jpaApi.em().merge((OrangeResult) baseResult);
}
}
我希望有一个比不得不做if / else并根据结果显式强制转换更优雅的解决方案。我正在研究使用泛型的
@DiscriminatorValue
注释之类的东西,但是这些似乎都要求BaseResult
也是一个实体,不是。 最佳答案
您应该使用@Inheritance
。然后,保存将非常简单:
public void save(final BaseResult baseResult) {
jpaApi.em().merge(baseResult);
}
使用哪种继承策略取决于您当前的数据库设计,但是我猜测您为每个子类都有一个表,因此如下所示:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseResult {
//...
}
@Entity
public class AppleResult extends BaseResult {
//...
}
在超类上具有
@Entity
并不是问题,因为无论如何它都是abstract
。同样,通常不应该使用
merge
,您应该在事务中操纵实体,并在提交事务后将其自动持久保存在数据库中:@Transactional //either this...
public void doStuff(final ResultCommand command) {
//begin transaction <-- ...or this
final BaseResult result = em.find(BaseResult.class, command.getResultId());
result.apply(command);
//end transaction
}