从Hibernate迁移到OpenJPA - 不提取OneToMany

时间:2013-05-09 00:14:24

标签: hibernate one-to-many openjpa

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

情况可归纳如下:我有两个实体成员用户名。成员可以有多个用户名。 Ii在数据库中由两个表(Member和Username)实现,其中username表包含member_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来加载数据。使用hibernate加载成员数据并隐式加载用户名工作得很好。 切换到OpenJPA后,usernames集合为null。当我在成员对象上调用 getUsernames()时,我仍然返回null并且不执行其他提取。我将日志级别增加到TRACE,并且看到只执行了对Member表的简单SQL提取。

我也尝试过添加 Fetch = EAGER Cascade = ALL ,但没有任何区别。

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

我错过了什么?

非常感谢

编辑1

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

编辑2

我检查过,如果行为与JPAContainer有关。因此我手动创建了EntityManager:

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

结果是一样的:我从Member表的列中获取数据,我也从成员中的@ManyToOne关系中获取数据 - 比如 status - 但不是@OneToMany关系。

编辑3

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

3 个答案:

答案 0 :(得分: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元素并在@JoinColumn上指定Member

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

答案 1 :(得分:0)

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

我尝试在eclipse构建中添加ant构建器,但即使在成功构建之后,使用指定的运行时启动应用程序也会失败,并显示没有执行增强的消息。

不建议使用运行时增强功能,所以我跳过了这个但是尝试了EclipseLink而不是......! Woohoo - 它可以在不对实现进行任何更改的情况下再次工作。

结论:并非所有称为“Apache”的内容都非常可靠且暂时非常值得推荐,以避免使用OpenJPA

答案 2 :(得分:0)

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

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)