标签: criteria-api

使用JPA Criteria API,您是否可以执行只获得一次连接的获取连接?

使用JPA 2.0.似乎默认情况下(没有显式提取),@OneToOne(fetch = FetchType.EAGER)在1 + N个查询中提取字段,其中N是包含定义与不同相关实体的关系的实体的结果数.使用Criteria API,我可能会尝试避免如下:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
Join<MyEntity, RelatedEntity> join = root.join("relatedEntity");
root.fetch("relatedEntity");
query.select(root).where(builder.equals(join.get("id"), 3));
Run Code Online (Sandbox Code Playgroud)

理想情况下,上述内容应与以下内容相同:

SELECT m FROM MyEntity m JOIN FETCH myEntity.relatedEntity r WHERE r.id = 3
Run Code Online (Sandbox Code Playgroud)

但是,条件查询导致根表不必要地连接到相关实体表两次; 一次用于获取,一次用于where谓词.生成的SQL看起来像这样:

SELECT myentity.id, myentity.attribute, relatedentity2.id, relatedentity2.attribute 
FROM my_entity myentity 
INNER JOIN related_entity relatedentity1 ON myentity.related_id = relatedentity1.id 
INNER JOIN related_entity relatedentity2 ON myentity.related_id = relatedentity2.id 
WHERE relatedentity1.id = 3
Run Code Online (Sandbox Code Playgroud)

唉,如果我只进行获取,那么我没有在where子句中使用的表达式.

我错过了什么,或者这是Criteria API的限制?如果是后者,这是否在JPA 2.1中得到纠正,还是有任何特定于供应商的增强功能?

否则,最好放弃编译时类型检查(我意识到我的示例不使用元模型)并使用动态JPQL TypedQueries.

java jpa jpql criteria-api

24
推荐指数
2
解决办法
5万
查看次数

JPA/Hibernate静态元模型属性未填充 - NullPointerException

我想将JPA2 Criteria API与元模型对象一起使用,这看起来很简单:

...
Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
... albm.get(JPAAlbum_.theme) ... ;
Run Code Online (Sandbox Code Playgroud)

但是这个Root.get总是抛出一个NullPointerException.JPAAlbum_.theme是由Hibernate自动生成的,看起来像

public static volatile SingularAttribute<JPAAlbum, JPATheme> theme;
Run Code Online (Sandbox Code Playgroud)

但它显然从未填充过.

我错过了框架初始化的一个步骤吗?

编辑:这是我在崩溃时如何使用JPA和元模型的片段:

    CriteriaBuilder cb = em.getCriteriaBuilder();

    CriteriaQuery<JPAAlbum> cq = cb.createQuery(JPAAlbum.class) ;
    Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
    cq.where(cb.equal(albm.get(JPAAlbum_.theme).get(JPATheme_.id),
                        session.getTheme().getId())) ;
Run Code Online (Sandbox Code Playgroud)

(JPAAlbum_是一个类,所以我就import在之前)和相关的堆栈跟踪:

Caused by: java.lang.NullPointerException
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)
    at net.wazari.dao.jpa.WebAlbumsDAOBean.getRestrictionToAlbumsAllowed(WebAlbumsDAOBean.java:55)
Run Code Online (Sandbox Code Playgroud)

编辑2:

在JBoss EntityManager指南中,我可以看到

当构建Hibernate EntityManagerFactory时,它将查找每个托管类型的规范元模型类,如果它找到任何它将向它们注入适当的元模型信息,如[JPA 2规范,第6.2节中所述] .2,页码200]

我也可以验证

     for (ManagedType o : em.getMetamodel().getManagedTypes()) {
            log.warn("___") ;
            for (Object p : o.getAttributes()) {
                log.warn(((Attribute)p).getName()) ;
            } …
Run Code Online (Sandbox Code Playgroud)

java hibernate nullpointerexception criteria-api jpa-2.0

22
推荐指数
3
解决办法
2万
查看次数

JPA Criteria Query不同

我正在尝试编写一个不同的条件查询,使用:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<RuleVar> query = builder.createQuery(RuleVar.class);
Root<RuleVar> ruleVariableRoot = query.from(RuleVar.class);
query.select(ruleVariableRoot.get("foo").<String>get("foo")).distinct(true);
Run Code Online (Sandbox Code Playgroud)

基于CriteriaQuery.select()的javadoc中的示例

CriteriaQuery<String> q = cb.createQuery(String.class);
 Root<Order> order = q.from(Order.class);
 q.select(order.get("shippingAddress").<String>get("state"));
Run Code Online (Sandbox Code Playgroud)

但是,这给了我一个错误:

The method select(Selection<? extends RuleVar>) in the type CriteriaQuery<RuleVar> is not applicable for the arguments (Path<String>)
Run Code Online (Sandbox Code Playgroud)

有人可以指出我做错了什么吗?或者如何从Path获取Selection对象?

java jpa criteria-api

22
推荐指数
1
解决办法
4万
查看次数

如何使CriteriaBuilder加入自定义"on"条件?

我想使用CriteriaBuilder在我加入2个表的地方进行查询.在MySQL中,我想要的查询看起来像这样:

SELECT * FROM order
LEFT JOIN item
ON order.id = item.order_id
AND item.type_id = 1
Run Code Online (Sandbox Code Playgroud)

我想获得所有订单,如果他们有#1类型的商品,我想加入这个商品.但是,如果没有找到#1类型的项目,我仍然想要获得订单.我无法弄清楚如何使用CriteriaBuilder进行此操作.我所知道的是:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
Root<Order> order = cq.from(Order.class);
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT);
Join<Item, Type> type = order.join(Item_.type, JoinType.LEFT);
cq.select(order);
cq.where(cb.equal(type.get(Type_.id), 1));
Run Code Online (Sandbox Code Playgroud)

此查询已中断,因为它在MySQL中产生类似的结果:

SELECT * FROM order
LEFT JOIN item
ON order.id = item.order_id
WHERE item.type_id = 1
Run Code Online (Sandbox Code Playgroud)

结果将只包含类型为#1的订单.没有订单被排除在外.如何使用CriteriaBuilder创建第一个示例中的查询?

jpa criteria-api jpa-2.0

22
推荐指数
1
解决办法
3万
查看次数

标准JPA 2有3个表格

我正在尝试创建一个标准来从3个表中检索一些对象(关联,更新和详细信息).详细信息引用了"关联"和"更新","更新"引用了"详细信息"列表.我的目标是在给定Associate id的情况下检索在指定字段中至少具有null值的Detail的更新列表.在JPQL中很容易做到,但客户说这必须用标准编码.

我的JPQL是:

public List<Update> getUpdates(long associateId) {
    TypedQuery<Update> query = em.createQuery("select distinct u from Update u, Detail dt, Associate a "
        + "where dt.update = u and dt.associate = a and a.associateId = :id and "
        + "dt.ack_date is null", Update.class);
    query.setParameter("id", associateId);
    return query.getResultList();
}
Run Code Online (Sandbox Code Playgroud)

我尝试了以下内容,但它只返回了数据库中的所有更新:

public List<Update> getUpdates(long associateId) {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Update> query = builder.createQuery(Update.class);

    Root<Update> fromUpdates = query.from(Update.class);
    Root<Associate> fromAssociate = query.from(Associate.class);
    Root<Detail> fromDetail = query.from(Detail.class);

    Join<Detail, Associate> associateJoin = fromDetail.join("associate");
    Join<Detail, Update> …
Run Code Online (Sandbox Code Playgroud)

java jpql criteria-api jpa-2.0

21
推荐指数
2
解决办法
4万
查看次数

JPA标准API - 与Spring Data JPA规范中的列表匹配

我想创建一个规范,将一个用户对象的组ID与一个id列表相匹配.我正在考虑使用isMember(就像在代码中一样),但该方法不会采用该列表.

public static Specification<User> matchCompanyIdsList(final List<Long> groupIds){
  return new Specification<User>() {
    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder){
      final Path<Group> group = root.<Group> get("group");
      return builder.isMember(company.<Long>get("id"), companyIds);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

如果我不在,我怎么办呢?

jpa criteria-api spring-data

20
推荐指数
1
解决办法
2万
查看次数

使用join的Spring Data JPA规范的不同结果

我有以下Specification用于查询Contact绑定到某些ManagedApplication实体的任何实体.我传入一个Collection<Long>包含ManagedApplication我正在搜索的实体的ID .

public static Specification<Contact> findByApp(final Collection<Long> appIds) {
    return new Specification<Contact>() {
        @Override
        public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) {            
            final Predicate appPredicate = root.join(Contact_.managedApplications)
                .get(ManagedApplication_.managedApplicationId).in(appIds);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我将此规范传递给.findAll()my 的方法,PagingAndSoringRepository以检索Page<Contact>包含Contact符合搜索条件的所有实体的方法.

这是Repository.

@Repository
public interface PagingAndSortingContactRepository extends PagingAndSortingRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {    
}
Run Code Online (Sandbox Code Playgroud)

以下是我如何调用该.findAll()方法.

final Page<Contact> contacts = pagingAndSortingContactRepository.findAll(ContactSpecification.findByApp(appIds), pageable);
Run Code Online (Sandbox Code Playgroud)

这将工作并返回与传入的id对应的Contact任何实体绑定的所有实体ManagedApplication.但是,由于我要调用实体.join() …

java hibernate jpa criteria-api spring-data-jpa

19
推荐指数
2
解决办法
2万
查看次数

在JPA 2中使用预测

我需要转换Hibernate条件查询,如下所示

curList = session.createCriteria(Islem.class)
                    .createAlias("workingDay", "d")
                    .setProjection(Projections.sum("amount"))
                    .add(Restrictions.eq("currency", CURRENCY))
                    .add(Restrictions.eq("product", product))
                    .add(Restrictions.ne("status", INACTIVE))
                    .add(Restrictions.eq("d.status", ACTIVE))
                    .getResultList();
Run Code Online (Sandbox Code Playgroud)

然而在JPA(2)中,我不知道如何实现投影 - 在这种情况下 - 总和.奇怪的是,Hibernate和JPA(甚至是Hibernate JPA 2)在标准查询中存在巨大差异.

我开始

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Islem> cq = cb.createQuery(Islem.class);
Root<Islem> isr = cq.from(Islem.class);
cq.select(isr).where(cb.equal(isr.get("currency"), CURRENCY), 
                     cb.notEqual(isr.get("status"), INACTIVE),
                     cb.equal(isr.get("product"), product));
Run Code Online (Sandbox Code Playgroud)

但是不知道如何在这里实现投影既不是别名

hibernate projection criteria-api hibernate-criteria jpa-2.0

18
推荐指数
1
解决办法
2万
查看次数

OpenJPA criteriaBuilder嵌套对象属性获取

OpenJPA中是否有任何方法可以通过CriteriaBuilder获取嵌套对象属性?

这是一个小案例.

@Entity
public class X {
       private Object Y;

       // getters, setters...
}

@Entity
public class Y {
       private String Z;

       // getters, setters...
}
Run Code Online (Sandbox Code Playgroud)

因此,在使用CriteriaBuilder时,我们使用X作为Root,即:

@PersistenceContext
private EntityManager entityManager;

//.....

Root<X> rootObj = criteriaBuilder.from(X.class);
CriteriaQuery<X> select;

String param1 = X.getY().getZ();

// initializing predicate, default value is TRUE
Predicate predicate1 = criteriaBuilder.isNull(null);

// construct search predicate which fails miserably due to IllegalArgumentExecption
if (X != null) {
predicate1 = criteriaBuilder.and(predicate1, criteriaBuilder.equal(rootObj.<String> get("Y.Z"), param1));}
Run Code Online (Sandbox Code Playgroud)

现在,我的悲痛就是 - > get("Y.Z")

CriteriaBuilder不知道反射取Z(但它可以并将解析Y).有没有办法直接从get()获取Z?

除了使用JPQL之外,我还可以想到另一种方法 …

java openjpa criteria-api

17
推荐指数
2
解决办法
9958
查看次数

使用jpa api标准加入不相关的实体

两个数据库表具有外键关系.

它们通过JPA 映射到两个实体AB,但是连接列是从实体中手动删除的,因此在JPA世界中,类AB不相关,您无法通过字段/属性从一个导航到另一个.

使用标准api是否可以创建一个连接两个表的查询?

我在互联网上找到的所有例子都使用连接列来实现目标,但是,如上所述,它已从代码中删除,因为大多数时候我对AB之间的关系不感兴趣而且我担心可能的开销.

java jpa join associations criteria-api

17
推荐指数
3
解决办法
2万
查看次数