@ElementCollection with Map <entity,embeddable =“”>其中Entity是Embeddable </entity的字段,>

时间:2012-08-15 17:28:37

标签: 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>();
....

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;
....

并且Instrument实体是:

@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实现。

1 个答案:

答案 0 :(得分:3)

  

所以我的问题是,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,而是使用Portfolio类中的地图字段上的注释@MapKeyJoinColumn来声明该列应该用作地图的连接列键。

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