【问题标题】:Hibernate Left Join to Subclass returns ProxyHibernate Left Join to Subclass 返回代理
【发布时间】:2018-03-20 15:56:00
【问题描述】:

我有一个基类的继承层次结构:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
abstract Instrument {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;

    @OneToMany(mappedBy = "instrument1", fetch = FetchType.LAZY)
    List<Market> markets;

    abstract Type getType(); // Type is an Enum containing Currency & Commodity
}

还有两个子类CommodityCurrency 例如

@Entity
@DiscriminatorValue("CUR")
@PrimaryKeyJoinColumn(name = "INS_ID"))
public class Currency extends Instrument {
    ...
    getType() {
        returns Type.Currency;
    }
}

每种工具都可以在多个市场上市:

@Entity
public class Market {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "INS_ID")
    private Instrument instrument1; // Currency or Commodity listed on the market

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "CUR_ID")
    private Currency instrument2; // Base currency of the market
}

我创建了一个CRUDRepository 方法来选择所有市场及其工具和基础货币:

@Query("SELECT m FROM Market m LEFT JOIN FETCH m.instrument1 LEFT JOIN FETCH m.instrument2")
public List<Market> findAllMarkets();

但由于某种原因,当我尝试执行以下操作时:

findAllMarkets()
    .stream()
    .filter(m -> m.getInstrument1().getType() == Type.Currency)
    .map(m -> (Currency) m.getInstrument1())
    .collect(toList());

我得到一个ClassCastException,因为Instrument1 实际上是Instrument 的代理类型,而不是我所期望的Currency。这似乎是间歇性发生的,有些是实际的 Currency 实例,有些是 instrument_$$_jvst965_19 代理。

有没有办法可以强制 Hibernate 不使用代理进行此查询?

【问题讨论】:

  • 目前看来这与休眠会话缓存有关

标签: hibernate spring-data-jpa hql


【解决方案1】:

我怀疑这与休眠会话或 L2 缓存有关。

在我的应用程序的其他地方,我在仪器上查询一个没有Left Join Fetch 的实体,例如喜欢:

SELECT m FROM Market m

我注意到,如果我将此调用更改为还包含Left Join Fetch,那么我的问题就解决了。或者在没有Left Join Fetch 的方法调用之前调用findAllMarkets 也解决了这个问题。

要阻止这种情况发生,您可以将@Proxy(lazy=false) 添加到您的基类中,例如

@Proxy(lazy=false)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
abstract Instrument {
    ...
}

但是,如果您调用 SELECT m FROM Market m,这将导致 Hibernates n+1 方法,因为它将选择所有市场,然后在单独的查询中加载每个工具。

【讨论】:

    猜你喜欢
    • 2021-10-19
    • 1970-01-01
    • 2011-10-13
    • 2011-08-03
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多