休眠:如何在不显式强制转换的情况下对继承类型结构建模并执行操作



我有一个应用程序,它使用传入的消息,解析消息中存在的数据,然后将规则应用于该数据。在">规则"实体上,有一列用于区分规则的类型

我想将规则的结果保留为单独的表或子类,具体取决于处理它们的规则类型

我目前正在通过创建一个父@MappedSuperclass(抽象)BaseResult 对象和一个扩展BaseResultAppleResultOrangeResult@Enitiy来解决这个问题。

我的问题是,鉴于下面的语句,我如何改进/注释模型中的对象,以便在访问/持久化它时不必对每个实例进行实例检查?现在,这就是我必须做的,以避免"baseresult不存在"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
}

最新更新