Hibernate继承-获取超类实例并将其转换为子类 [英] Hibernate Inheritance - Getting superclass instance and casting into subclass

查看:143
本文介绍了Hibernate继承-获取超类实例并将其转换为子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这种情况.

有地块,有的是住宅用地,有的是商业用地.

There are plots, some are residential plots and some are commercial plots.

也有所有者.但是所有者只能购买一块土地,并且可以是住宅或商业用地.

There are also owners. But an owner can buy only a plot and it can be residential or commercial.

所以,这是我的代码.

@Entity
@Table(name = "PLOT")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Plot {
  private int id;
  private String number;
  private List<Owner> owners = new ArrayList<>();

  // getters and setters...
}


@Entity
@Table(name = "RESIDENTIAL_PLOT")
@PrimaryKeyJoinColumn(name = "PLOT_ID")
public class ResidentialPlot extends Plot {
  // Some fields
}


@Entity
@Table(name = "COMMERCIAL_PLOT")
@PrimaryKeyJoinColumn(name = "PLOT_ID")
public class CommercialPlot extends Plot {
  // Some fields
}


@Entity
@Table(name = "OWNER")
public class Owner {
  private int id;
  private String name;
  private Plot plot;

  // getters and setters
}

一切正常,但是当我打电话给owner.getPlot()时 我期待的是ResidentialPlotCommercialPlot实例 因此,我可以使用instanceof运算符来应用适当的操作. 但是它不能同时满足这两个条件!

All works well, but when I call owner.getPlot() I was expecting ResidentialPlot or CommercialPlot instance So, I can apply appropriate operation by using instanceof operator. But it does not satisfy both conditions!

我在做什么错了?

推荐答案

您没有使用多态性,它在JPA环境中的危害更大.

You're not using polymorphism, and it hurts even more in a JPA environment.

观察到此行为的原因是由于Hibernate使用了代理.当Hibernate加载所有者时,它无法确定该地块是商业用地还是住宅用地.它必须做一个额外的查询才能知道.因此,它使用惰性代理初始化plot字段,该代理是动态生成的类的实例,该类扩展了Plot,但既不是CommercialPlot也不是ResidentialPlot.

The reason you observe this behavior is because of the usage of proxies by Hibernate. When Hibernate loads an Owner, it can't tell if the plot is a commercial or residential plot. It would have to do an additional query to know it. So it initializes the plot field with a lazy proxy, which is an instance of a dynamically generated class which extends Plot, but is neither a CommercialPlot nor a ResidentialPlot.

在代理上调用方法时,代理会通过从数据库获取Plot数据进行初始化,然后将其委托到CommercialPlot或ResidentialPlot的实例.

When a method is called on the proxy, the proxy initializes itself by getting the Plot data from the database, and it delegates to an instance of CommercialPlot or ResidentialPlot.

解决方案是使用多态性.将一个抽象方法添加到Plot类(例如,getType()isResidential()),并在两个子类中都实现它.如果由于需要依赖实体类型但不应该包含在实体本身中的业务逻辑而无法实现,请使用访客模式.

The solution is to use ploymorphism. Add an abstract method to the Plot class (getType(), or isResidential(), for example), and implement it in both subclasses. If that isn't possible because you need business logic that depends on the entity type but shouldn't be in the entity itself, use the visitor pattern.

我写了博客文章如果您需要更多详细信息,请使用法语.也许Google翻译可以为您提供帮助.

I wrote a blog article on this subject if you need more details, but it's in French. Maybe Google Translate could help you.

这篇关于Hibernate继承-获取超类实例并将其转换为子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆