3

我已经包含了在将 JPA 类构建到显示的表模式时遇到的错误......任何人都可以指导我如何解决这个错误。以及当其中一个键实际上是外键时如何制作复合键。我的注释有什么问题?

错误

org.apache.openjpa.util.MetaDataException:类型“class Specialty”指定的id类与类的主键字段不匹配。
确保您的身份类具有与持久类型相同的主键,包括 pk 字段类型。不匹配的属性:“personId”

表架构

创建表位置(
  id int 主键,
  城市 varchar(255),
  状态 varchar(100),
  国家 varchar(255)
);
创建表人(
  id int 主键,
  名称 varchar(100)
);
创建表摄影师(
  id int 主键在删除级联上更新级联上引用 Person(id),
  liveIn int not null 引用 Location(id) on update cascade on delete no action
);
创建表专业(
  摄影师 int 在删除级联上更新级联时引用摄影师(id),
  类型枚举('肖像','风景','运动'),
  主键(摄影师,类型)
);
创建表照片(
  id int 主键,
  takeAt 时间戳不为空,
  takeBy int 在删除时更新级联引用摄影师(id)无操作,
  photosedAt int 引用 Location(id) 更新级联删除无操作,
  类型枚举('肖像','风景','运动')
);
创建表外观(
  在删除级联上显示更新级联上的 int 引用 Person(id),
  isShownIn int 在删除级联上更新级联上引用照片(id),
  主键(显示,isShownIn)
);

课程

人.java

@实体
公共类人实现可序列化{

    @ID
    @GeneratedValue(策略 = GenerationType.IDENTITY)
    私人 int id;

    私有字符串名称;


位置.java

@实体
公共类位置实现可序列化{

    @ID
    @GeneratedValue(策略 = GenerationType.IDENTITY)
    私人 int id;

    私人字符串城市;

    私有字符串状态;

    私有字符串国家;


摄影师.java

@实体
公共类摄影师实现可序列化{

    @ID
    @ManyToOne
    @Column(name = "id")
    私人人personId;

    @ManyToOne
    @Column(name = "livesIn")
    私人位置住在;

照片.java

@实体
公共类照片实现可序列化{

    @ID
    @Column(name = "id")
    @GeneratedValue(策略 = GenerationType.IDENTITY)
    私人 int id;

    // 外键
    @ManyToOne
    @JoinColumn(name = "takenBy")
    私人摄影师拍摄;

    // 外键
    @ManyToOne
    @JoinColumn(name = "photographedAt")
    私人拍摄地点;

    @基本(可选=假)
    @Column(名称=“takenAt”,可插入=假,可更新=假)
    @Temporal(TemporalType.DATE)
    私人拍摄日期;

    @Enumerated(EnumType.STRING)
    私有 PhotoType 类型;

照片类型

 
公共枚举 PhotoType {
    肖像(“肖像”),风景(“风景”),运动(“运动”);
    私有字符串类型;

    PhotoType(字符串类型){
        this.type = 类型;
    }

    公共字符串 getType() {
        返回类型;
    }

}

专业.java

 
导入 java.io.Serializable;

导入 javax.persistence.Column;
导入 javax.persistence.Embeddable;
导入 javax.persistence.EmbeddedId;
导入 javax.persistence.Entity;
导入 javax.persistence.EnumType;
导入 javax.persistence.Enumerated;
导入 javax.persistence.Id;
导入 javax.persistence.JoinColumn;
导入 javax.persistence.ManyToOne;
导入 javax.persistence.OneToMany;
导入 javax.persistence.OneToOne;

@实体
公共类专业实现可序列化{

    @EmbeddedId
    受保护的SpecialtyPK专业PK;

    公共专业(){
        极好的();
    }

    公共专业(SpecialtyPK specialPK){
        极好的();
        this.specialtyPK = 专业PK;
    }

}

@可嵌入
类 SpecialtyPK 实现可序列化 {

    @ManyToOne
    @Column(name = "id")
    私人摄影师 personId;

    @Enumerated(EnumType.STRING)
    私有 PhotoType 类型;

    /*
     *(非 Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @覆盖
    公共 int hashCode() {
        最终 int 素数 = 31;
        整数结果 = 1;
        结果 = 素数 * 结果
                + ((personId == null) ? 0 : personId.hashCode());
        结果 = 素数 * 结果 + ((type == null) ? 0 : type.hashCode());
        返回结果;
    }

    /*
     *(非 Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @覆盖
    公共布尔等于(对象 obj){
        如果(这 == 对象)
            返回真;
        如果(obj == null)
            返回假;
        if (getClass() != obj.getClass())
            返回假;
        SpecialtyPK 其他 = (SpecialtyPK) obj;
        if (personId == null) {
            if (other.personId != null)
                返回假;
        } else if (!personId.equals(other.personId))
            返回假;
        如果(类型!= other.type)
            返回假;
        返回真;
    }

    公共专业PK(){
        极好的();
        // TODO 自动生成的构造函数存根
    }

    public SpecialtyPK(Photographer personId, PhotoType type) {
        极好的();
        this.personId = personId;
        this.type = 类型;
    }

}

尝试使用复合键也失败并给出了同样的错误。

很多互联网搜索还没有找到任何解决方案。

4

2 回答 2

1

在我看来,您有一个复合主键,但您通过注释告诉 JPA,您有一个嵌入的主键。就像我告诉每个第一次参加项目的人一样:

首先让最简单的事情开始工作,而不考虑效率并根据客户需求进行优化。

过早的优化是多软件问题的根源。

于 2012-11-25T05:21:49.300 回答
0

问题是2倍。一个问题是 SpecialtyPK 中的 personId 映射。@Column 用于基本映射;您需要使用 @JoinColumn 注释指定用于连接的列。

第二个也是更重要的是,主键类不应该包含关系——它是否可嵌入定义为主键类并不重要,它应该只包含基本映射或其他主键(在 JPA 2.0 中允许派生 ID,这意味着可以嵌套关键类)。因此,您将需要一个具有“int”类型的 personId 的 SpecialtyPK 类。然后,您可以在 Specialty 中指定一个 ManyToOne 映射并添加 @MapsId 以将其指向 int,这样您只需要设置关系而不需要管理可嵌入对象中的基本映射。

@Entity
public class Specialty implements Serializable {

    @EmbeddedId
    protected SpecialtyPK specialtyPK;

    @MapsId("personId")
    protected Photographer photographer;
..

class SpecialtyPK implements Serializable {

    @Column(name = "id")
    private int personId;//defaults to basic

..

或者您可以删除 embeddedId 并将摄影师标记为 id。

于 2012-11-26T15:52:01.817 回答