带有实体或ID的JPQL @NamedQuery?

时间:2012-07-23 06:57:59

标签: jpa ejb-3.1

抱歉,如果重复。

是否可以或建议业务层使用对象而不是ID?

SELECT c
FROM Child AS c
WHERE c.parent = :parent
public List<Child> list(final Parent parent) {

    // does parent must be managed?
    // how can I know that?
    // have parent even been persisted?

    return em.createNamedQuery(...).
        setParameter("parent", parent);
}

这就是我的工作方式。

SELECT c
FROM Child AS c
WHERE c.parent.id = :parent_id
public List<Child> list(final Parent parent) {

    // wait! parent.id could be null!
    // it may haven't been persisted yet!

    return list(parent.getId());
}

public List<Child> list(final long parentId) {
    return em.createNamedQuery(...).
        setParameter("parent_id", parentId);
}

更新的问题--------------------------------------

是否可以在同一个JTA中说明每个可以注入@EJB的JAX-RS或JAX-WS类?

这是我一直很好奇的原始问题。

假设我们有两个EJB。

@Stateless
class ParentBean {

    public Parent find(...) {
    }
}

@Stateless
class ChildBean {

    public List<Child> list(final Parent parent) {
    }

    public List<Child> list(final long parentId) {
    }
}

使用任何EJB客户端的正确方法是什么?

@Stateless // <<-- This is mandatory for being injected with @EJB, right?
@Path("/parents/{parent_id: \\d+}/children")
class ChildsResource {

    @GET
    @Path
    public Response list(@PathParam("parent_id") final long parentId) {

        // do i just have to stick to this approach?
        final List<Child> children1 = childBean.list(parentId);

        // is this parent managed?
        // is it ok to pass to other EJB?
        final Parent parent = parentBean.find(parentId);

        // is this gonna work?
        final List<Child> children2 = childBean.list(parent);

        ...
    }

    @EJB
    private ParentBean parentBean;

    @EJB
    private ChildBean childBean;
}

2 个答案:

答案 0 :(得分:2)

以下内容仅作为问题回答“是否可以或建议业务层使用对象而不是ID?”,因为遗憾的是我不完全理解第二个问题“做任何JAX-RS或JAX每个可以用@EJB注入的-WS类可以在同一个JTA中说出来吗?“

有可能。在大多数情况下也建议。 ORM的全部目的是我们可以操作对象及其关系,而不是它们在数据库中的表示。

实体的ID(特别是在代理ID的情况下)通常是在我们靠近存储本身时才有意义的概念。当只提供持久性本身需要访问id时,设计访问id为protected的方法通常是有意义的。当我们这样做时,会向实体用户发布较少的噪音。

也像往常一样有效例外。例如,可以发现通过线路移动整个实体太耗费资源并且具有id列表而不是实体列表是优选的。在问题确实存在之前,不应该做出这样的设计决定。

答案 1 :(得分:1)

如果尚未持久化父级,则查询将不起作用,并且执行它没有多大意义。如果父母没有被坚持,那么你有责任避免执行它。但我不会让它成为find方法本身的责任。只是在方法的文档中明确说明父作为参数传递的方法必须具有ID,或者至少是持久的。无需与实体经理进行相同的验证。

如果它已被持久化,但尚未发生刷新,则实体管理器必须在执行查询之前进行刷新,正好使查询找到新父级的子级。

至少在Hibernate中,您可以使用分离的父级执行查询。如果ID在那里,查询将使用它并执行查询。