@ElementCollection with Map <Entity,Embeddable>,其中Entity是Embeddable的字段

hen*_*lst 5 java hibernate jpa map

在搜索了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>();
....
Run Code Online (Sandbox Code Playgroud)

可嵌入的OpenPosition如下:

@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;
....
Run Code Online (Sandbox Code Playgroud)

工具实体为:

@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();
    ....
Run Code Online (Sandbox Code Playgroud)

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

通过调试可以看到,尽管在Instrument对象中设置了ID,但所有其他字段均为null。

所以我的问题是,JPA2.0是否允许ElementCollection的键是实体,该实体也作为Embeddable值的字段存在?如果是这样,我该怎么办。如果不是,最好的替代方法是改为使用Instrument实体的ID作为键?

提前致谢。

ps我正在使用休眠4.1.4 JPA实现。

jus*_*... 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;
Run Code Online (Sandbox Code Playgroud)

就我而言,Carrier 是 an @Entity,FreightBid 是 an@Embedded

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

我搞砸了什么。

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

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