读取具有一对多关系的JPA模型时生成不完整的JSON错误

读取具有一对多关系的JPA模型时生成不完整的JSON错误,json,jackson,jax-rs,eclipselink,one-to-many,Json,Jackson,Jax Rs,Eclipselink,One To Many,我正在使用JPA EclipseLink对用例和PainPoint之间的一对多关系进行建模。我可以很好地插入值。此后,我使用JAX-RS使用GET方法检索数据。GET方法失败,错误为生成不完整的JSON 控制台日志: @NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")}) @Id @GeneratedValue(strategy = GenerationType.AUTO)

我正在使用JPA EclipseLink对用例和PainPoint之间的一对多关系进行建模。我可以很好地插入值。此后,我使用JAX-RS使用GET方法检索数据。GET方法失败,错误为生成不完整的JSON

控制台日志:

@NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "UseCaseID")
private int UseCaseID;

@Column(name = "Description")
private String Description;

@OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
@NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "PainPointID")
private int PainPointID;

@Column(name = "PainPointDescription")
private String PainPointDescription;

@ManyToOne
@JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
private UseCase usecase;
UseCase useCase = new UseCase("Description 1");
PainPoint painPoint1 = new PainPoint("Pain Point 1", useCase);
useCase.getPainPoints().add(painPoint1);
em.persist(useCase);
@GET
@Path("/")
public List<UseCase> getUseCases() {

List<UseCase> retVal = null;

EntityManagerFactory emf = Utility.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();

retVal = em.createNamedQuery("getAllUseCases").getResultList();

return retVal;
}
  • [EL Fine]:在用例(UseCaseID,描述)中插入值(?,) 绑定=>[1,说明]
  • [EL Fine]:插入痛点 (PainPointID,PainPointDescription,USECASE_ID)值(?,?)绑定 =>[2,痛点1,1]
  • [EL Fine]:选择UseCaseID,从USECASE中选择描述
  • 2017年11月17日下午7:16:22 org.eclipse.yasson.internal.Marshaller:Generating 不完全JSON
用例:

@NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "UseCaseID")
private int UseCaseID;

@Column(name = "Description")
private String Description;

@OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
@NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "PainPointID")
private int PainPointID;

@Column(name = "PainPointDescription")
private String PainPointDescription;

@ManyToOne
@JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
private UseCase usecase;
UseCase useCase = new UseCase("Description 1");
PainPoint painPoint1 = new PainPoint("Pain Point 1", useCase);
useCase.getPainPoints().add(painPoint1);
em.persist(useCase);
@GET
@Path("/")
public List<UseCase> getUseCases() {

List<UseCase> retVal = null;

EntityManagerFactory emf = Utility.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();

retVal = em.createNamedQuery("getAllUseCases").getResultList();

return retVal;
}
数据加载器:

@NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "UseCaseID")
private int UseCaseID;

@Column(name = "Description")
private String Description;

@OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
@NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "PainPointID")
private int PainPointID;

@Column(name = "PainPointDescription")
private String PainPointDescription;

@ManyToOne
@JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
private UseCase usecase;
UseCase useCase = new UseCase("Description 1");
PainPoint painPoint1 = new PainPoint("Pain Point 1", useCase);
useCase.getPainPoints().add(painPoint1);
em.persist(useCase);
@GET
@Path("/")
public List<UseCase> getUseCases() {

List<UseCase> retVal = null;

EntityManagerFactory emf = Utility.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();

retVal = em.createNamedQuery("getAllUseCases").getResultList();

return retVal;
}
UseCaseService:

@NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "UseCaseID")
private int UseCaseID;

@Column(name = "Description")
private String Description;

@OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
@NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@NotNull
@Column(name = "PainPointID")
private int PainPointID;

@Column(name = "PainPointDescription")
private String PainPointDescription;

@ManyToOne
@JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
private UseCase usecase;
UseCase useCase = new UseCase("Description 1");
PainPoint painPoint1 = new PainPoint("Pain Point 1", useCase);
useCase.getPainPoints().add(painPoint1);
em.persist(useCase);
@GET
@Path("/")
public List<UseCase> getUseCases() {

List<UseCase> retVal = null;

EntityManagerFactory emf = Utility.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();

retVal = em.createNamedQuery("getAllUseCases").getResultList();

return retVal;
}
@GET
@路径(“/”)
公共列表getUseCases(){
列表retVal=null;
EntityManagerFactory emf=Utility.getEntityManagerFactory();
EntityManager em=emf.createEntityManager();
retVal=em.createNamedQuery(“getAllUseCases”).getResultList();
返回返回;
}

在循环引用的getter方法或任何其他派生字段上添加注释@jsonbttransient(包:javax.json.bind.annotation.jsonbttransient)。这相当于用于XML生成的@XmlTranisent注释,并将防止转换为JSON进入无限循环

我想这取决于您的工具集,但对于使用NetBeans的我来说,当自动生成实体类时,会添加XML注释,但不会添加JSON注释。根据上面所说的,只需将每个@xmltransive与等效的@JsonbTransient进行匹配即可。您可以添加以下Maven依赖项

<dependency>
    <groupId>javax.json.bind</groupId>
    <artifactId>javax.json.bind-api</artifactId>
    <version>1.0</version>
</dependency>

javax.json.bind

这很可能是由循环引用引起的,有两种方法处理此问题,如中所述:

  • @杰索尼奥雷
  • @JsonManagedReference和@JsonBackReference

  • 我建议您采用第二种方法,并添加以下两种注释,以避免循环引用问题:

    @OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JsonBackReference                ///// ADD THIS ANNOTATION
    private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
    
    
    @ManyToOne
    @JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
    @JsonManagedReference              ///// ADD THIS ANNOTATION
    private UseCase usecase;
    
    @OneToMany(mappedBy=“usecase”,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
    @JsonBackReference//添加此批注
    private Collection painPoints=new ArrayList();
    @许多酮
    @JoinColumn(name=“USECASE\u ID”,referencedColumnName=“UseCaseID”)
    @JsonManagedReference///添加此批注
    私人用例用例;
    

    更多信息:

    @NamedQueries({@NamedQuery(name = "getAllUseCases", query = "SELECT c FROM UseCase c")})
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NotNull
    @Column(name = "UseCaseID")
    private int UseCaseID;
    
    @Column(name = "Description")
    private String Description;
    
    @OneToMany(mappedBy="usecase", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    private Collection<PainPoint> painPoints = new ArrayList<PainPoint>();
    
    @NamedQueries({@NamedQuery(name = "getAllPainPoints", query = "SELECT c FROM PainPoint c")})
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NotNull
    @Column(name = "PainPointID")
    private int PainPointID;
    
    @Column(name = "PainPointDescription")
    private String PainPointDescription;
    
    @ManyToOne
    @JoinColumn (name="USECASE_ID", referencedColumnName="UseCaseID")
    private UseCase usecase;
    
    UseCase useCase = new UseCase("Description 1");
    PainPoint painPoint1 = new PainPoint("Pain Point 1", useCase);
    useCase.getPainPoints().add(painPoint1);
    em.persist(useCase);
    
    @GET
    @Path("/")
    public List<UseCase> getUseCases() {
    
    List<UseCase> retVal = null;
    
    EntityManagerFactory emf = Utility.getEntityManagerFactory();
    EntityManager em = emf.createEntityManager();
    
    retVal = em.createNamedQuery("getAllUseCases").getResultList();
    
    return retVal;
    }
    

    显然,JSON生成与JPA API无关,所以为什么不调试到JSON生成的位置,使用什么代码……我想我应该在原始帖子中包含这些信息。但似乎有某种循环递归搜索正在进行。例如,用例有痛点。PainPoint与用例相关联。所以JSON出现了错误。。。不知道如何在一对多关系中绕过它。我删除了引用用例的PainPoint对象上的getter和setter,现在它似乎可以工作了。哈哈,应该猜到了。希望我不会遇到其他问题。我使用了来自和works的@JsonIdentityInfo,谢谢。@AndréLuítomaszdio我很高兴它对您有所帮助。