18

这似乎是一个非常简单的问题,但我还没有找到明确的答案。我有一个 DAO 类,它自然地使用标准查询来查询数据库。所以我想知道使用相同的 CriteriaBuilder 实现来创建不同的查询是否安全,或者我是否必须为每个查询创建新的 CriteriaBuilder 实例。以下代码示例应该说明我想要做什么:

public class DAO() {  
    CriteriaBuilder cb = null;

    public DAO() {
        cb = getEntityManager().getCriteriaBuilder();
    }

    public List<String> getNames() {
        CriteriaQuery<String> nameSearch = cb.createQuery(String.class);
        ...
    }

    public List<Address> getAddresses(String name) {
        CriteriaQuery<Address> nameSearch = cb.createQuery(Address.class);
        ...
    }
}

这样做可以吗?

4

4 回答 4

16

阅读JPA 2.0 规范 (JSR 317) 的第3.1.1 节 EntityManager 接口中的 javadoc :

/**
 * Return an instance of CriteriaBuilder for the creation of
 * CriteriaQuery objects.
 * @return CriteriaBuilder instance
 * @throws IllegalStateException if the entity manager has
 *         been closed
 */
public CriteriaBuilder getCriteriaBuilder();

紧随其后的评论是:

从实体管理器获得的QueryTypedQueryCriteriaBuilderMetamodelEntityTransaction对象在该实体管理器打开时有效。

以及第6.5 节构建标准查询

CriteriaBuilder接口用于构造CriteriaQuery 对象。通过or 接口的方法 CriteriaBuilder 访问实现 。getCriteriaBuilderEntityManagerEntityManagerFactory

我希望能够CriteriaBuilder在实体管理器的生命周期内重用一个来创建许多查询。但这是我的解释。然而,我最初的测试似乎证实了这并没有什么问题(相反确实很可怕)。

于 2010-05-21T23:42:29.680 回答
1

有趣的问题。我会说“当然,这就是标准查询的全部意义”,但我在这里找不到一个词来支持这一点:http: //java.sun.com/javaee/6/docs/tutorial/doc/gjivm .html

但是:如果它们不可重用,那将意味着实体管理器实际上修改了它们,这将是糟糕的 api 设计。所以:我希望它们是可重复使用的,但我不能保证

于 2010-05-19T19:12:12.540 回答
1

这是安全的。

您可以从 EntityManagerFactory 获取 CriteriaBuilder。在休眠实现中,criteriaBuilder 是 EntityManagerFactory 的实例字段。所以在传统情况下,没有风险。

于 2011-02-03T17:53:43.107 回答
1

Eclipse Link 在您启动查询时以随机方式(有时有效,有时无效)生成错误(EclipseLink-6089、org.eclipse.persistence.exceptions.QueryException),然后在执行第一个查询之前生成另一个错误。有关详细信息,请参阅Stack OverflowJBoss 问题

如果您一一运行查询或计划使用 Hibernate,则重用 CriteriaBuilder 没有问题。

于 2012-01-20T20:55:41.163 回答