Hibernate Left Join to Subclass返回Proxy

kpbwa7wx  于 2023-10-23  发布在  其他
关注(0)|答案(2)|浏览(105)

我有一个继承层次与基类:

@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不对这个查询使用代理?

neekobn8

neekobn81#

我怀疑这与Hibernate Session或L2 Cache有关。
在我的应用程序的其他地方,我正在查询一个没有仪器上的Left Join Fetch的实体,例如。例如:
SELECT m FROM Market m
我注意到,如果我改变这个调用,也包括Left Join Fetch,那么我的问题就解决了。在方法调用之前调用findAllMarkets而不使用Left Join Fetch也解决了这个问题。
为了防止这种情况发生,你可以将@Proxy(lazy=false)添加到你的基类中,例如。

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

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

kd3sttzy

kd3sttzy2#

如果您获得代理,则意味着您的一个市场实体已经在持久性单元中。如果你不需要代理,请确保在查询数据库之前没有管理任何市场实体。

相关问题