0

我尝试将应用程序从 Hibernate 迁移到 OpenJPA,并且“突然”不再获取 @OneToMany 关系。

情况可以总结如下:我有两个 Entity MemberUsername。一个成员可以有多个用户名。Ii 在数据库中由两个表(成员和用户名)实现,其中用户名表包含成员 ID 作为外键列。

这导致实体:

@Table(name="member")
public class Member implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(unique=true, nullable=false)
private int id;
    ...
    @OneToMany(mappedBy="member")
private List<Username> usernames;
    ...
}

@Entity
@Table(name="username")
public class Username implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(insertable=false, updatable=false, unique=true, nullable=false)
private int id;

    //bi-directional many-to-one association to Member
    @ManyToOne
@JoinColumn(name="member_id", nullable=false)
private Member member;
    ...

两个实体类都具有用于属性的公共 setter 和 getter 以及默认构造函数。(我尝试了一种“即插即用”的方法,并在 Eclipse 中从现有数据库自动创建了这些类)。

这些类在persistence.xml文件中声明

<persistence-unit name="...">
    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
    <class>allwi.data.jpa.Member</class>
    <class>allwi.data.jpa.Username</class>

我正在使用 VAADIN 框架的 JPAContainer 来加载数据。使用休眠加载成员数据并隐式加载用户名效果很好。切换到 OpenJPA 后,用户名集合为空。当我在成员对象上调用getUsernames()时,我仍然返回 null 并且没有执行额外的提取。我将日志级别增加到 TRACE 并看到只执行了对成员表的简单 SQL 提取。

我也已经尝试添加Fetch=EAGERCascade=ALL没有区别。

我必须犯一个愚蠢的错误,因为似乎我是唯一遇到这个问题的人。如前所述,我使用的是VAADIN JPAContainer,即基本上我对实体管理器的创建没有太大影响。

我错过了什么?

非常感谢

编辑 1

改进了代码片段并添加了对 DB 设计的一些解释。

编辑 2

我检查了该行为是否与 JPAContainer 相关。因此,我手动创建了 EntityManager:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory(...);
    EntityManager em = emf.createEntityManager();       
    Member m = em.find(Member.class, 14661667);

结果是一样的:我从 Member 表的列中获取数据,我还从 Member 中的 @ManyToOne 关系中获取数据——比如状态——但不是 @OneToMany 关系的集合。

编辑 3

我正在使用 PostgreSQL 作为数据库。

4

3 回答 3

0

好的 - 我有一种直觉,这个问题与增强策略有关。我使用了 Eclipse 插件的构建时增强功能并遇到了上述问题(并且看到了一些警告,这些类已增强为 1.x 而不是“2”)。

我尝试在 Eclipse 构建中添加 ant 构建器,但即使构建成功,使用分配的运行时启动应用程序也失败,并显示未执行任何增强的消息。

不推荐运行时增强,所以我跳过了这个,而是尝试了 EclipseLink ......而且!?Woohoo - 它再次工作而无需对实现进行任何更改。

结论:并非所有称为“Apache”的东西都很棒且可靠,目前强烈建议避免使用 OpenJPA

于 2013-05-10T02:04:39.687 回答
0

根据注释上的mappedBy元素判断,您将此关系映射为双向关系。@OneToMany您需要在实体上添加@ManyToOne注释。Username

@Entity
@Table(name="username")
public class Username implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(insertable=false, updatable=false, unique=true, nullable=false)
    private int id;

    @ManyToOne
    @JoinColumn(name="id") //this depends on your column name
    private Member member;

如果这实际上是单向关系,则需要删除mappedBy元素并指定@JoinColumnonMember

@Table(name="member")
public class Member implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(unique=true, nullable=false)
    private int id;

    @Column(name="date_of_birth")
    private Timestamp dateOfBirth;
    ...

    @OneToMany()
    @JoinColumn(name="id") //this depends on the name of the foreign key column
    private List<Username> usernames;
    ...
于 2013-05-09T00:18:31.993 回答
0

或许你应该尝试使用 eager fetch 类型:

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
于 2015-05-12T14:05:08.237 回答