2012-08-15 58 views
4

在搜索完JPA文档和各种帖子之后,我很困惑以下是否可以用JPA2.0。我刚刚开始与JPA,所以请原谅我,如果我做了一些愚蠢的事情,@ElementCollection with Map <Entity,Embeddable>其中Entity是Embeddable的字段

我的域模型有一个“投资组合”,其中包含零个或多个“未平仓头寸”。一个职位由一个“工具”(这是一个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 
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作为密钥吗?

在此先感谢。

p.s.我正在使用hibernate 4.1.4 JPA实现。

+0

AFAIK你不能在Embeddable中使用实体。嵌入式应只包含基本类型。也不要在你的实体中使用'HashMap',而是使用'Map'接口。欢迎来到stackoverflow的方式;-) – siebz0r 2012-08-16 10:43:07

+0

@ siebz0r感谢您的反馈和欢迎。我相信JPA1.0中仅允许使用基本映射,但JPA2.0指出可嵌入对象允许所有关系 - 请参阅[链接](http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Relationships )。 Re:'Map' vs'HashMap',我不确定你的意思。该字段确实具有类型'Map',但是在实例化它时,我必须使用具体的类(即'HashMap') – pwrex 2012-08-16 13:20:44

回答

2

所以我的问题是,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; 

在我的情况下,运营商是一个@Entity和FreightBid是@Embedded

我已经能够保持和检索正确包含此映射的实体。

我搞砸了什么。

你应该从OpenPosition类中删除领域protected Instrument instrument;,而使用注释@MapKeyJoinColumn对投资组合类地图领域申报至极列应作为联接列到地图的关键。

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