5

在搜索了 JPA 文档和各种帖子之后,我对 JPA2.0 是否可以实现以下操作感到困惑。我刚从 JPA 开始,如果我在做一些愚蠢的事情,请原谅,

我的域模型有一个“投资组合”,其中包含零个或多个“未平仓头寸”。一个仓位由一个“工具”(它是一个 JPA 实体)和一个价格(双倍)组成。投资组合如下:

@Entity (name = "portfolio")
public class Portfolio {
    @Id
    @Column (name = "id")
    @GeneratedValue
    private long id;

    @ElementCollection (fetch = FetchType.EAGER)
    @CollectionTable (name = "portfolio_entry", joinColumns = @JoinColumn (name = "portfolio_id"))
    private final Map<Instrument, OpenPosition> positions = new HashMap<Instrument, OpenPosition>();
....

OpenPosition Embeddable 如下:

@Embeddable
public class OpenPosition extends Position {
    @ManyToOne (targetEntity = InstrumentImpl.class, optional = false)
    @JoinColumn (name = "instrument_id", nullable = false)
    protected Instrument instrument;

    @Column (name = "price", nullable = false)
    protected double price;
....

仪器实体是:

@Entity (name="instrument")
public class Instrument {
    @Id
    @Column(name = "id")
    @GeneratedValue
    private long id;

    @Column(name = "isin", nullable = false)
    private String isin;
....    
    @Override 
    public int hashCode() {
        int hash = 17;
        hash = 31 * hash + isin.hashCode();
    ....

当我尝试使用它时,架构被创建并且我能够持久化投资组合,但是当我尝试检索它们时,我在 Instrument 类的 hashCode 方法中得到一个 NullPointerException。似乎 JPA 正在尝试获取哈希码来构建 Map 键,但 Instrument 对象尚未加载。

通过调试可以看出,虽然在 Instrument 对象中设置了 id,但其他字段都是 null。

所以我的问题是,JPA2.0 是否允许 ElementCollection,其中键是一个实体,它也作为 Embeddable 值的字段存在?如果是这样,我在搞砸什么。如果没有,最好的解决方法是使用 Instrument 实体的 id 作为键吗?

提前致谢。

ps 我正在使用hibernate 4.1.4 JPA 实现。

4

1 回答 1

4

所以我的问题是,JPA2.0 是否允许 ElementCollection,其中键是一个实体,它也作为 Embeddable 值的字段存在?

是的,我设法用这个映射做到了:

@ElementCollection( targetClass = FreightBid.class )
@MapKeyJoinColumn( name = "carrier_id", referencedColumnName = "id" )
@CollectionTable( name = "freight_bid",
    joinColumns = @JoinColumn( name = "offer_pool_id" ) )
@Access( AccessType.FIELD )
private Map<Carrier,FreightBid> bidsByCarrier;

就我而言, Carrier 是一个@Entity, FreightBid 是一个@Embedded

我已经能够正确地保存和检索包含此地图的实体。

我在搞砸什么。

您应该protected Instrument instrument;OpenPosition类中删除该字段,而是使用@MapKeyJoinColumnPortfolio 类中映射字段上的注释来声明应该将哪个列用作映射键的连接列。

此外,最好避免在充当映射键的对象的 hashCode 方法中使用除 id 之外的其他字段……您的 JPA 实现者可能会搞砸。

于 2016-12-01T18:01:19.747 回答