JPA 双向 OneToMany 没有给我所需的集合

JPA Bi-directional OneToMany does not give me the desired collection

我正在尝试将 oracle 数据库模型映射到 JPA 实体(使用 eclipselink)- 我有以下简单设置:

table 主键id的程序 table multi_kupon 具有复合主键 id、spil 和外键 program_id

当我尝试使用简单的 select 获取程序时,我希望得到一个列表 multi_kupon 的但我得到一个大小为 0 的列表。我已经确定当我这样做时 带有连接的 select 我从程序和 multi_kupon.

获取数据

我认为这与我与这两个实体的关系有关 - 希望有人能指出我的错误

来自实体 'Program' 的代码段:

@Entity
@Table(name = "PROGRAM", schema = "", catalog = "")
public class Program implements Serializable{

  @Id
  private Integer id;

  private List<MultiKupon> MultiKuponList;

  @OneToMany(mappedBy = "program", fetch =  FetchType.EAGER)
  @JoinColumns({@JoinColumn(name = "id", referencedColumnName = "id"),
  @JoinColumn(name = "spil", referencedColumnName = "spil")})
  public List<MultiKupon> getMultiKuponList() {
    return multiKuponList;
  }

来自实体 'MultiKupon' 的代码段:

@Entity
@Table(name = "MULTI_KUPON", schema = "", catalog = "")
public class MultiKupon implements Serializable {

  private Integer id;
  private String spil;

  private Program program;

  @ManyToOne
  public Program getProgram() {
    return program;
  }

我的无状态 bean:

@Stateless
public class PostSessionBean {

  public Program getProgramById(int programId) {

String programById = "select p from Program p where p.id = :id";
Program program = null;
try {
  Query query = em.createQuery(programById);
  query.setParameter("id", programId);
  program = (Program) query.getSingleResult();

我确实得到了正确的程序实体和数据,但是列表 multi_kupon 数据大小为 0

我这里哪里做错了??

根据http://sysout.be/2011/03/09/why-you-should-never-use-getsingleresult-in-jpa/

尝试检索列表的第一个程序对象:

List<Program> pList = query.getResultList();
if(!pList.isEmpty()){
   return pList.get(0);
}

映射不正确,因为您指定了 OneToMany 是 mappedBy = "program" 并且它应该使用连接列。只能使用一个或另一个,因为有一个 'program' 映射,我建议你使用:

@OneToMany(mappedBy = "program", fetch = FetchType.EAGER) public 列表 getMultiKuponList()

然后在 MultiKupon 的 ManyToOne 映射上定义连接列,以定义程序的外键应使用哪些字段 table。

既然你把这段关系变成了双向关系,你也必须维护你们关系的双方。这意味着每次您添加一个 MultiKupon 并希望它与一个程序相关联时,您必须让它引用该程序,并将实例添加到该程序的集合中。如果不这样做,您将 运行 陷入这种情况,即缓存的程序与数据库中的程序不同步。

通常让双方保持同步要便宜得多,但如果这不是一个选项,您可以通过调用 em.refresh(program) 来纠正问题(或只是验证情况是否如此) .如果映射设置正确,实例及其列表将用数据库中的内容重新填充。