我尝试将应用程序从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作为数据库。
答案 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)