11

我有两个 DTO 对象,分别是 A 和 B,它们具有 getter 和 setter,用于从数据库中获取数据。问题是当我调用 A 时,B 被调用并且 B 再次指向 A 并创建了一个循环。

我不能忽略/隐藏创建循环的方法。我需要获取 A 和 B 的全部数据。

有什么办法可以实现吗?

请帮忙

这是导致问题的我的代码。这是调用环境 DTO 的应用程序 DTO

@OneToMany(mappedBy="application", fetch=FetchType.LAZY
        ,cascade=CascadeType.ALL
        )
public Set<EnvironmentDTO> getEnvironment() {
    return environment;
}

public void setEnvironment(Set<EnvironmentDTO> environment) {
    this.environment = environment;
}

这是调用应用程序 DTO 的环境 DTO

@ManyToOne(targetEntity=ApplicationDTO.class )
@JoinColumn(name="fk_application_Id") 
public ApplicationDTO getApplication() {
    return application;
}

public void setApplication(ApplicationDTO application) {
    this.application = application;
}

这里循环正在创建

这是我的休息电话,它将以 XML 格式给出结果,我认为在创建 XML 循环时正在创建

@GET
@Path("/get")
@Produces({MediaType.APPLICATION_XML})
public List<ApplicationDTO> getAllApplications(){
    List<ApplicationDTO> allApplication = applicationService.getAllApplication();
    return allApplication;
}

这是应用程序 DTO 类

@Entity
@Table(name="application")
@org.hibernate.annotations.GenericGenerator(
name ="test-increment-strategy",strategy = "increment")

@XmlRootElement
public class ApplicationDTO implements Serializable {

@XmlAttribute
public Long appTypeId;

private static final long serialVersionUID = -8027722210927935073L;

private Long applicationId;

private String applicationName;

private ApplicationTypeDTO applicationType;

private String applicationDescription;

private Integer owner;

private Integer createdBy;

private Integer assignedTo;

private Date createTime;

private Date modifiedTime;

private Set<EnvironmentDTO> environment;

@Id
@GeneratedValue(generator = "test-increment-strategy")
@Column(name = "applicationId")
public Long getApplicationId() {
    return applicationId;
}

private void setApplicationId(Long applicationId) {
    this.applicationId = applicationId;
}

@Column(name = "applicationName")
public String getApplicationName() {
    return applicationName;
}

public void setApplicationName(String applicationName) {
    this.applicationName = applicationName;
}

@ManyToOne(targetEntity=ApplicationTypeDTO.class 
        ,fetch = FetchType.LAZY
        )
@JoinColumn(name="applicationType")

public ApplicationTypeDTO getApplicationType() {
    return applicationType;
}

public void setApplicationType(ApplicationTypeDTO applicationType) {
    this.applicationType = applicationType;
}

@Column(name = "description")
public String getApplicationDescription() {
    return applicationDescription;
}

public void setApplicationDescription(String applicationDescription) {
    this.applicationDescription = applicationDescription;
}

@Column(name = "owner")
public Integer getOwner() {
    return owner;
}

public void setOwner(Integer owner) {
    this.owner = owner;
}

@Column(name = "createdBy")
public Integer getCreatedBy() {
    return createdBy;
}

public void setCreatedBy(Integer createdBy) {
    this.createdBy = createdBy;
}

@Column(name = "assignedTo")
public Integer getAssignedTo() {
    return assignedTo;
}

public void setAssignedTo(Integer assignedTo) {
    this.assignedTo = assignedTo;
}

@Column(name = "createTime")
public Date getCreateTime() {
    return createTime;
}

public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}

@Column(name = "modifiedTime")
public Date getModifiedTime() {
    return modifiedTime;
}

public void setModifiedTime(Date modifiedTime) {
    this.modifiedTime = modifiedTime;
}

@OneToMany(mappedBy="application", fetch=FetchType.LAZY
        ,cascade=CascadeType.ALL
        )
public Set<EnvironmentDTO> getEnvironment() {
    return environment;
}

public void setEnvironment(Set<EnvironmentDTO> environment) {
    this.environment = environment;
}

这是环境 DTO 类

@Entity
@Table(name="environment")

@org.hibernate.annotations.GenericGenerator(
name = "test-increment-strategy",
strategy = "increment")
@XmlRootElement
public class EnvironmentDTO implements Serializable {

@XmlAttribute
public Long envTypeId;

@XmlAttribute
public Long appId;

private static final long serialVersionUID = -2756426996796369998L;

private Long environmentId;

private String environmentName;

private EnvironmentTypeDTO environmentType;

private Integer owner;

private Date createTime;

private Set<InstanceDTO> instances;

private ApplicationDTO application;

@Id
@GeneratedValue(generator = "test-increment-strategy")
@Column(name = "envId")
public Long getEnvironmentId() {
    return environmentId;
}

private void setEnvironmentId(Long environmentId) {
    this.environmentId = environmentId;
}

@Column(name = "envName")
public String getEnvironmentName() {
    return environmentName;
}

public void setEnvironmentName(String environmentName) {
    this.environmentName = environmentName;
}

@ManyToOne(targetEntity=EnvironmentTypeDTO.class)
@JoinColumn(name = "envType")
public EnvironmentTypeDTO getEnvironmentType() {
    return environmentType;
}

public void setEnvironmentType(EnvironmentTypeDTO environmentType) {
    this.environmentType = environmentType;
}

@Column(name = "owner")
public Integer getOwner() {
    return owner;
}

public void setOwner(Integer owner) {
    this.owner = owner;
}

@Temporal(TemporalType.DATE)
@Column(name = "createTime")
public Date getCreateTime() 
{
    return createTime;
}

public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}

@OneToMany(mappedBy="environment", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
public Set<InstanceDTO> getInstances() {
    return instances;
}

public void setInstances(Set<InstanceDTO> instances) {
    this.instances = instances;
}

@ManyToOne(targetEntity=ApplicationDTO.class )
@JoinColumn(name="fk_application_Id")
//@XmlTransient 
public ApplicationDTO getApplication() {
    return application;
}

public void setApplication(ApplicationDTO application) {
    this.application = application;
}
4

3 回答 3

11

您的对象图是循环的。这并没有本质上的错误,这是使用 JPA 的自然结果。

您的问题不在于您的对象图是循环的,而是您以无法处理循环的格式对其进行编码。这不是 Hibernate 问题,而是 JAXB 问题。

我的建议是阻止 JAXB 尝试编组该类的application属性EnvironmentDTO。如果没有这个属性,循环图就会变成一棵树。您可以通过使用 注释该属性来做到这一点@XmlTransient

(坦白:我是通过阅读Doughan 先生的博客文章了解到这个注释的,我是在阅读他对这个问题的回答后才发现的!)

于 2013-06-25T12:12:33.567 回答
5

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB (JSR-222)专家组的成员。

MOXy 提供了@XmlInverseReference处理这个用例的扩展。以下是如何将此映射应用于具有双向关系的两个实体的示例。

顾客

import javax.persistence.*;

@Entity
public class Customer {

    @Id
    private long id;

    @OneToOne(mappedBy="customer", cascade={CascadeType.ALL})
    private Address address;

}

地址

import javax.persistence.*;
import org.eclipse.persistence.oxm.annotations.*;

@Entity
public class Address implements Serializable {

    @Id
    private long id;

    @OneToOne
    @JoinColumn(name="ID")
    @MapsId
    @XmlInverseReference(mappedBy="address")
    private Customer customer;

}

了解更多信息

于 2013-06-25T13:11:35.853 回答
1

我的建议是不要将您的 JPA 实体类暴露给您的 Web 服务。您可以创建不同的 POJO 类并将您的 JPA 实体转换为 POJO。例如:

这是您的 JPA 实体

import javax.persistence.*;

@Entity
public class Customer {

    @Id
    private long id;

    @OneToOne(mappedBy="customer", cascade={CascadeType.ALL})
    private Address address;

}

你应该为你的网络服务使用这个类:

public class CustomerModel{
    private long id;
    //you can call different WS to get the Address class, or combine to this model

    public void setFromJpa(Customer customer){
        this.id = customer.id;
    }
}
于 2017-05-01T01:06:27.580 回答