【问题标题】:The type of field isn't supported by declared persistence strategy "OneToMany"声明的持久性策略“OneToMany”不支持字段类型
【发布时间】:2011-01-30 13:37:56
【问题描述】:

我们是 JPA 的新手,并试图建立一个非常简单的一对多关系,其中名为 Message 的 pojo 可以拥有一个由名为 GROUP_ASSOC 的连接表定义的整数组 ID 列表。这是 DDL:

创建表 "APP"."MESSAGE" (
        "MESSAGE_ID" INTEGER NOT NULL 始终作为身份生成(从 1 开始,按 1 递增)
    );

ALTER TABLE "APP"."MESSAGE" 添加约束 "MESSAGE_PK" PRIMARY KEY ("MESSAGE_ID");

创建表“APP”。“GROUP_ASSOC”(
        "GROUP_ID" INTEGER NOT NULL,
        “MESSAGE_ID”整数非空
    );

ALTER TABLE "APP"."GROUP_ASSOC" 添加约束 "GROUP_ASSOC_PK" PRIMARY KEY ("MESSAGE_ID", "GROUP_ID");

ALTER TABLE "APP"."GROUP_ASSOC" 添加约束 "GROUP_ASSOC_FK" FOREIGN KEY ("MESSAGE_ID")
    REFERENCES "APP"."MESSAGE" ("MESSAGE_ID");

这里是pojo:

@Entity
@Table(name = "MESSAGE")
public class Message {
    @Id
    @Column(name = "MESSAGE_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int messageId;

    @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
    private List groupIds;

    public int getMessageId() {
        return messageId;
    }
    public void setMessageId(int messageId) {
        this.messageId = messageId;
    }
    public List getGroupIds() {
        return groupIds;
    }
    public void setGroupIds(List groupIds) {
        this.groupIds = groupIds;
    }
}

我知道这是错误的,因为 groupIds 属性没有 @Column 映射到 GROUP_ASSOC.GROUP_ID,但希望这能说明我们正在尝试做的事情。当我们运行以下测试代码时,我们得到<openjpa-1.2.3-SNAPSHOT-r422266:907835 fatal user error> org.apache.openjpa.util.MetaDataException: The type of field "pojo.Message.groupIds" isn't supported by declared persistence strategy "OneToMany". Please choose a different strategy.

Message msg = new Message();
List groups = new ArrayList();
groups.add(101);
groups.add(102);
EntityManager em = Persistence.createEntityManagerFactory("TestDBWeb").createEntityManager();
em.getTransaction().begin();
em.persist(msg);
em.getTransaction().commit();

救命!

【问题讨论】:

    标签: jpa openjpa


    【解决方案1】:

    当您使用 JPA 时,您应该考虑对象和对象之间的关系,并且您应该将您的对象模型而不是 ids 映射到您的关系模型(可以使用 @ 映射基本值的 List 987654321@ 虽然在 JPA 2.0 中,但我之前所说的仍然适用)。

    这里,(假设这确实是MessageGroupAssoc 之间的一对多 关系,而不是@ 之间的多对多 关系987654327@ 和 Group 实体)你应该有这样的东西:

    @Entity
    @Table(name = "MESSAGE")
    public class Message implements Serializable {
        @Id
        @Column(name = "MESSAGE_ID")
        @GeneratedValue(strategy = GenerationType.IDENTITY)    
        private Long messageId;
    
        @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)    
        private List<GroupAssoc> groupAssocs = new ArrayList<GroupAssoc>();
    
        public Long getMessageId() {
            return messageId;
        }
        public void setMessageId(Long messageId) {
            this.messageId = messageId;
        }
    
        public List<GroupAssoc> getGroupAssocs() {
            return groupAssocs;
        }
        public void setGroupAssocs(List<GroupAssoc> groupAssocs) {
            this.groupAssocs = groupAssocs;
        }
    
        // equals() and hashCode()
    }
    

    GroupAssoc 的另一个实体。

    PS:您的 DDL 看起来确实像 MESSAGEGROUP 之间的 (M:N) 关系(或者我不理解 GROUP_ASSOC 的 PK 约束)但您没有显示任何 FK 约束GROUP_ID 所以我不能 100% 确定。但如果是这种情况,那么您应该使用@ManyToMany 而不是@OneToMany

    【讨论】:

    • 非常感谢您的帮助。我应该提到我们的应用程序需要显示 groupIds(在 UI 中),并且 groupId 的列表是我们最终需要通过消息查询的内容。我认为这是 M:N 关系,因为两个按摩可能共享相同的 groupId。
    • 我的 DDL 是我对如何有效地建模这个整数列表的最佳猜测,因此它可能存在问题(我是 UI 开发人员而不是 DBA)。创建一个单独的GroupAssoc pojo 似乎很麻烦,特别是如果我们必须创建第三个身份类(因为它具有复合主键)只是为了查询给定消息的 groupId 列表。
    • @Robert 您不必创建第三个实体,JPA 在数据库级别抽象实现。所以你会得到一个GroupAssoc 的列表并在列表上迭代以获取每个 id。
    • 所以GroupAssoc pojo 不需要@Id@IdClass
    • @Robert 在 600 个字符的框中不容易讨论 :) GroupAssoc 确实需要有一个用 @Id 注释的属性,我没说不需要。我说的是“连接表”不需要第三个实体。 JPA 可以将Message-*--*-Group 对象模型映射到数据库中的Message-0--n-MessageGroup-m--0-Group 表示,而无需MessageGroup 的实体。我希望它更清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 2011-07-22
    • 1970-01-01
    • 2014-01-16
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多