JPA2:复合键(无法映射)

时间:2012-05-23 10:03:58

标签: spring hibernate jpa jpa-2.0 spring-data-jpa

我正在尝试使用JPA2映射以下数据库结构:

ASSET
ID: assetId
...

PARTY
ID: partyId
...

PARTYASSET
ID: partyId
ID: assetId
ID: relationshipType

PARTYASSET的主键是PARTY和ASSET的外键和一个附加列的组合:relationshipType。

由于列relationshipType,我不能使用@ManyToMany注释我必须使用@ManyToOne和@OneToMany,如此链接中所述: http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany

我尝试过以下指南,但没有帮助: http://www.kawoolutions.com/Technology/JPA,_Hibernate,_and_Co./JPA_Composite_Key_Variants#JPA_2.0_@IdClass

你能帮我吗?

我尝试了以下方法: (继承用于其他目的)

派对类

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("PARTY")
public class Party implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long partyId;

    @OneToMany(mappedBy = "party")
    private Set<PartyAsset> partyAsset;
    ... 
}

资产类

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("ASSET")
public class Asset implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long assetid;

    @OneToMany(mappedBy = "asset")
    private Set<PartyAsset> partyAsset;
    ...
}

使用@IdClass:

PartyAsset类

@Entity
@IdClass(PartyAssetPK.class)
public class PartyAsset implements Serializable {
    private static final long serialVersionUID = 1L;

    public static enum RelationshipType {
        OWNER, TENANT, SECONDARY_CONTACT, SUPPLIER
    }

    @Id
    @Enumerated(EnumType.STRING)
    private RelationshipType relationshipType;

    @Id
    @ManyToOne
    @JoinColumn(name="partyId")
    private Party party;

    @Id
    @ManyToOne
    @JoinColumn(name="assetId")
    private Asset asset;
    ...
}

PartyAssetPK类

public class PartyAssetPK implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long partyId;
    private Long assetId;
    private PartyAsset.RelationshipType relationshipType;
}

上面的代码抛出异常:

  

在实体PartyAsset:assetId

中找不到@IdClass的属性

@IdClass的替代

PartyAsset类

@Entity
@IdClass(PartyAssetPK.class)
public class PartyAsset implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private Long partyId;
    @Id
    private Long assetId;

    public static enum RelationshipType {
        OWNER, TENANT, SECONDARY_CONTACT, SUPPLIER
    }

    @Id
    @Enumerated(EnumType.STRING)
    private RelationshipType relationshipType;

    @ManyToOne
    @JoinColumn(name="partyId")
    @MapsId("partyId")
    private Party party;

    @ManyToOne
    @JoinColumn(name="assetId")
    @MapsId("assetId")
    private Asset asset;    
}

抛出异常:

  

找不到超类型

使用@EmbeddedId

PartyAsset类

@Entity
public class PartyAsset implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    public PartyAssetPK id;

    public static enum RelationshipType {
        OWNER, TENANT, SECONDARY_CONTACT, SUPPLIER
    }

    @MapsId("relationshipType")
    @Enumerated(EnumType.STRING)
    private RelationshipType relationshipType;

    @ManyToOne
    @JoinColumn(name="partyId")
    @MapsId("partyId")
    private Party party;

    @ManyToOne
    @JoinColumn(name="assetId")
    @MapsId("assetId")
    private Asset asset;    
}

PartyAssetPK类

@Embeddable
public class PartyAssetPK implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long partyId;
    private Long assetId;
    private PartyAsset.RelationshipType relationshipType;
}

抛出异常;

  

引起:org.springframework.beans.factory.BeanCreationException:   创建名为'entityManagerFactoryBean'的bean时出错   类   com.ardan1.propertymanagement.test.config.TestApplicationContext:   调用init方法失败;嵌套异常是   java.lang.NullPointerException引起:   java.util.Hashtable.put中的java.lang.NullPointerException(未知   来自)java.util.Properties.setProperty(未知来源)at   org.hibernate.cfg.annotations.SimpleValueBinder.setType(SimpleValueBinder.java:227)     在   org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:188)     在   org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:203)     在   org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2013)     在   org.hibernate.cfg.AnnotationBinder.fillComponent(AnnotationBinder.java:2385)

我有以下库(使用Maven):

<hibernate.version>4.1.2</hibernate.version>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>${hibernate.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>1.0.3.RELEASE</version>
</dependency>

2 个答案:

答案 0 :(得分:0)

我认为您可以使用@JoinColumn进行映射。以下代码使用Spring Data JPA。

BaseEntity.java

import java.io.Serializable;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.data.jpa.domain.AbstractPersistable;

public abstract class BaseEntity<PK extends Serializable> extends AbstractPersistable<PK> implements Serializable {

    private static final long serialVersionUID = 201304010827L;

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

}

AssetEntity.java

@Entity
@Table(name = "tb_asset")
@AttributeOverride(name = "id", column = @Column(name = "AssetID"))
public class AssetEntity extends BaseEntity<Long> {

    @Column(name = "desc")
    private String desciption;

    // getters and setters...

}

PartyEntity.java

@Entity
@Table(name = "tb_party")
@AttributeOverride(name = "id", column = @Column(name = "PartyID"))
public class PartyEntity extends BaseEntity<Long> {

    private String party;

    // Getters and setters.

}

要使用@JoinColumn和@Embeddable,我们有PartyAsset.java。

@Embeddable
public class PartyAssetKey implements Serializable {

    @ManyToOne
    @JoinColumn(name = "party_id", referencedColumnName = "id")
    private PartyEntity partyEntity;

    @ManyToOne
    @JoinColumn(name = "asset_id", referencedColumnName = "id")
    private AssetEntity assetEntity;

    private Long relationshipType;

}

最后是PartyAssetEntity.java

@Entity
@Table(name = "tb_party_asset")
public class PartyAsset extends BaseEntity<PartyAssetKey> {

    private Long type;

    // Getters and setters.

}

我用葡萄牙语写了一篇关于Spring Data JPA的帖子:http://wpattern.com/blog/post/2012/11/25/Introducao-ao-Spring-Data-JPA-(Contextualizacao)-Parte-01.aspx

答案 1 :(得分:0)

@Techky你通过尝试复合键的所有选项做得很好,同时我也得到了完全相同的错误。

对于使用@EmbeddedId的情况,这是我的解决方案。这段代码我在一个类中编写,在Entity类中。

  • Class MyEntity - 这是我的表的实际实体类。 &#34; OtherFields&#34;是那些不属于主键的字段。
  • Class MyEntityPrimaryKeys - 这是为我的复合键创建的类,它为我的&#34; MyEntity&#34;类。 ROLLNO和AGE一起成为主键。

MyEntity.java

@Entity
@Table(name = "myTable")
public class MyEntity extends GenericPersistableEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId 
    MyEntityPrimaryKeys id;//Composite Primary key

    //Composite fields can be declared here for getter and setters
    @Column(name = "ROLLNO")
    private Long RollNo;

    //Composite fields can be declared here for getter and setters
    @Column(name = "AGE")
    private Long age;

    @Column(name = "OtherFields"
    private Long OtherFields;

    //getter and setters comes here
}



@Embeddable
 class MyEntityPrimaryKeys  implements Serializable{

    private static final long serialVersionUID = 1L;

    @Column(name = "ROLLNO")
    Long RollNo;

    @Column(name = "AGE")
    Long age;

    @Override
    public int hashCode() {
        HashCodeBuilder hcb = new HashCodeBuilder();
        hcb.append(RollNo);
        hcb.append(age);
        return hcb.toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof MyEntityPrimaryKeys)) {
            return false;
        }
        MyEntityPrimaryKeys that = (MyEntityPrimaryKeys) obj;
        EqualsBuilder eb = new EqualsBuilder();
        eb.append(RollNo, that.RollNo);
        eb.append(age, that.age);
        eb.append(tonMonth, that.tonMonth);
        eb.append(tonYear, that.tonYear);
        return eb.isEquals();
    }
}

希望这会有所帮助!!