JPA EntityGraph没有工作;始终加载相关集合

时间:2014-09-02 21:00:27

标签: java jpa jaxb

我正在尝试使命名实体图正常工作。基本上,我有一个客户可以拥有零个或多个地址。当我查询获取客户列表时,我想要客户的字段,但不是关联的地址。当我查询特定客户时,我想要它的字段和所有相关的地址。所以,我一直试图使用命名实体图,因为它们似乎解决了这种情况。我创建了一个获取基本信息,另一个获取所有内容。不幸的是,当我使用任何一个图表时,我仍然总是得到一切。我确信我犯了一个简单的错误,但我似乎无法找到它。我很感激你的帮助,弄清楚我的错误。相关代码如下......

感谢您的时间和建议, 麦克

/////////////////////////////////////////////////////////
// ENTITIES
/////////////////////////////////////////////////////////

@Entity
@Table(name = "customers")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c")})

@NamedEntityGraphs({
    @NamedEntityGraph(
        name="previewCustomerEntityGraph", 
        attributeNodes={
            @NamedAttributeNode("id"),
            @NamedAttributeNode("displayAs"),
            @NamedAttributeNode("rowVersion")
        }
    ),
    @NamedEntityGraph(
        name="fullCustomerEntityGraph", 
        attributeNodes={
            @NamedAttributeNode("id"),
            @NamedAttributeNode("displayAs"),
            @NamedAttributeNode("rowVersion"),
            @NamedAttributeNode(value = "addressCollection", subgraph = "addressCollection")
        },
        subgraphs = @NamedSubgraph(
            name = "addressCollection", 
            attributeNodes = {
                @NamedAttributeNode("id"),
                @NamedAttributeNode("displayAs"),
                @NamedAttributeNode("rowVersion")
            }
        )
    )
})
public class Customer implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "Id")
    @XmlAttribute(required=true)
    private Long id;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 256)
    @Column(name = "DisplayAs")
    @XmlElement(required=true, nillable=false)
    private String displayAs;

    @Basic(optional = true)
    @Size(max = 256)
    @Column(name = "Name")
    @XmlElement(required=true, nillable=true)
    private String name;    

    @Basic(optional = false)
    @NotNull
    @XmlElement(required=true, nillable=false)
    @Column(name = "RowVersion")
    @Version
    private Timestamp rowVersion;


    @OneToMany(mappedBy = "customerId",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Collection<Address> addressCollection;

//@XmlTransient
public Collection<Address> getAddressCollection() {
    return addressCollection;
}

public void setAddressCollection(Collection<Address> addressCollection) {
    this.addressCollection = addressCollection;
}

    // Object methods have been removed to save space
}


@Entity
@Table(name = "addresses")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Address.findAll", query = "SELECT a FROM Address a")})
public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @XmlAttribute(required=true)
    @Column(name = "Id")
    private Long id;

    @Basic(optional = false)
    @NotNull
    @Column(name = "RowVersion")
    @Temporal(TemporalType.TIMESTAMP)
    @XmlElement(required=true, nillable=true)
    private Date rowVersion;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 256)
    @Column(name = "DisplayAs")    
    @XmlElement(required=true, nillable=true)
    private String displayAs;

    @JoinColumn(name = "CustomerId", referencedColumnName = "Id")
    @ManyToOne
    private Customer customerId;

    // Object methods have been removed to save space
}





/////////////////////////////////////////////////////////
// QUERIES
/////////////////////////////////////////////////////////

    protected T find(Object id) {                   
        // Filter to only return entities belonging to the tenant.       

        EntityGraph eg = getEntityManager().getEntityGraph("fullCustomerEntityGraph");

        javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
        javax.persistence.criteria.Root<T> from = cq.from(entityClass);        
        javax.persistence.criteria.CriteriaQuery<T> select = cq.select(from);      
        cq.where(cb.and(
                cb.equal(from.<T>get("id"), id)
        ));

        javax.persistence.TypedQuery<T> tq = getEntityManager().createQuery(select);

        tq.setHint("javax.persistence.fetchgraph", eg);

        return getSingleResultOrNull(tq);
    }

    protected List<T> findAll() {       
        // Filter to only return entities belonging to the tenant.

        EntityGraph eg = getEntityManager().getEntityGraph("previewCustomerEntityGraph");

        javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
        javax.persistence.criteria.Root<T> from = cq.from(entityClass);        
        javax.persistence.criteria.CriteriaQuery<T> select = cq.select(from);       
        javax.persistence.TypedQuery<T> tq = getEntityManager().createQuery(select);

        tq.setHint("javax.persistence.fetchgraph", eg);

        return tq.getResultList();
    }

    protected T getSingleResultOrNull(javax.persistence.TypedQuery<T> query) {
        query.setMaxResults(1);
        List<T> list = query.getResultList();
        if (list.isEmpty()) {
            return null;
        }

        return list.get(0);
    }

1 个答案:

答案 0 :(得分:0)

序列化程序正在调用getAddressCollection

请注意@XmlTransient在地址列表中发表了评论。放回此注释,然后重试。

在这种情况下,自动序列化将始终避免列表。如果您需要在其他地方返回完整的图表,我建议您编写自己的序列化逻辑或创建Value Object以准确保存您需要的内容并让序列化程序完成工作。