Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Criteria API:如果[NOT]NULL,则选择表达式<;价值>;_Java_Jpa_Criteria Api - Fatal编程技术网

Java Criteria API:如果[NOT]NULL,则选择表达式<;价值>;

Java Criteria API:如果[NOT]NULL,则选择表达式<;价值>;,java,jpa,criteria-api,Java,Jpa,Criteria Api,我正在尝试将以下简单查询转换为JPA criteria API: SELECT ticket_action.ticket_id IS NOT NULL, ticket.id FROM ticket LEFT OUTER JOIN ticket_action ON ticket.id = ticket_action.ticket_id 我尝试了两种方法: 使用criteriaBuilder.function(“ISNULL”,Boolean.class,ticketAction.get(tick

我正在尝试将以下简单查询转换为JPA criteria API:

SELECT ticket_action.ticket_id IS NOT NULL, ticket.id
FROM ticket
LEFT OUTER JOIN ticket_action ON ticket.id = ticket_action.ticket_id
我尝试了两种方法:

  • 使用
    criteriaBuilder.function(“ISNULL”,Boolean.class,ticketAction.get(ticketAction\uuu.ticketId))
    :如果
    ISNULL
    类似于
    ISNOTNULL
    (对于MySQL/MariaDB数据库),则问题在于没有否定
  • 使用
    criteriaBuilder.isNotNull(ticketAction.get(ticketAction\uuu.ticketId))
    :但这将返回一个
    谓词
    ,而select语句只接受
    表达式
    s
  • 扩展目标:与按票证分组相同。票证id不为空


    表结构符合要求 结果: 最后,我使用了一个construtor查询,它接收
    ticket\u action
    id
    。在构造函数中有关于状态的决定:
    this.hasTicketAction=tickettactionid!=无效
    不是很令人满意,但很有效


    谢谢大家发布您的答案

    您可以使用以下示例在选择表达式中生成is not null:

    CriteriaQuery<Tuple> cq = entityManager.getCriteriaBuilder().createTupleQuery();
    Root<Test> pet = cq.from(Test.class);
    cq.multiselect(pet.get("id1").isNotNull(), pet.get("id2"));
    
    CriteriaQuery cq=entityManager.getCriteriaBuilder().createTupleQuery();
    根pet=cq.from(测试类);
    cq.multiselect(pet.get(“id1”).isNotNull(),pet.get(“id2”);
    

    我认为生成的查询将抛出一个查询语法异常,因为jpa/hibernate可能不支持在select表达式中使用is not null。如果是这种情况,那么一个可能的解决方案可能是将is not null放在where子句中。您可以在此处找到该情况的示例

    您可以使用以下示例在select表达式中生成is not null:

    CriteriaQuery<Tuple> cq = entityManager.getCriteriaBuilder().createTupleQuery();
    Root<Test> pet = cq.from(Test.class);
    cq.multiselect(pet.get("id1").isNotNull(), pet.get("id2"));
    
    CriteriaQuery cq=entityManager.getCriteriaBuilder().createTupleQuery();
    根pet=cq.from(测试类);
    cq.multiselect(pet.get(“id1”).isNotNull(),pet.get(“id2”);
    

    我认为生成的查询将抛出一个查询语法异常,因为jpa/hibernate可能不支持在select表达式中使用is not null。如果是这种情况,那么一个可能的解决方案可能是将is not null放在where子句中。您可以在这里找到该案例的示例

    一种工作方法是使用
    CriteriaBuilder。选择case(…)

    使用
    DTO
    like(
    Object[]
    也会这样做,但从一开始就是类型安全的)

    可以通过以下查询获得结果

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<TicketTuple> cq = cb.createQuery(TicketTuple.class);
    Root<Ticket> from = cq.from(Ticket.class);
    Join<Ticket, TicketAction> join = from.join("ticketAction", JoinType.LEFT);
    
    Expression<Boolean> caseHasAction = cb.<Boolean>selectCase()
          .when(cb.isNotNull(join), true)
          .otherwise(false);
    
    cq.multiselect(
          caseHasAction.as(Boolean.class)
         ,from.get("id")
    );
    
    将返回具有和不具有
    TicketAction
    票证的计数

    我不知道实际的原因,但问题似乎在于
    cb.isNotNull(..)
    (my)
    JPA
    implementation要么总是获取看起来不为
    null的内容
    要么根据检查
    null
    的方式,它创建一些
    内部联接
    ,以便从结果集中删除
    null


    (我正在使用OpenJPA)

    一种工作方法是使用
    CriteriaBuilder.selectCase(…)

    使用
    DTO
    like(
    Object[]
    也会这样做,但从一开始就是类型安全的)

    可以通过以下查询获得结果

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<TicketTuple> cq = cb.createQuery(TicketTuple.class);
    Root<Ticket> from = cq.from(Ticket.class);
    Join<Ticket, TicketAction> join = from.join("ticketAction", JoinType.LEFT);
    
    Expression<Boolean> caseHasAction = cb.<Boolean>selectCase()
          .when(cb.isNotNull(join), true)
          .otherwise(false);
    
    cq.multiselect(
          caseHasAction.as(Boolean.class)
         ,from.get("id")
    );
    
    将返回具有和不具有
    TicketAction
    票证的计数

    我不知道实际的原因,但问题似乎在于
    cb.isNotNull(..)
    (my)
    JPA
    implementation要么总是获取看起来不为
    null的内容
    要么根据检查
    null
    的方式,它创建一些
    内部联接
    ,以便从结果集中删除
    null


    (我正在使用OpenJPA)

    对于此查询,您需要具有类型为的集合属性。 此外,我还必须使用而不是
    TicketTuple
    (答案中引用),因为在处理没有票证的票证操作时,它给出了
    IllegalArgumentException
    (参数类型不匹配),我不知道您的模式中是否存在这种可能性

    EclipseLink JPA实现,Derby db

    在class
    Ticket
    中,您必须具有以下属性:

    @OneToMany(mappedBy = "ticket")
    private Collection<TicketAction> ticketActions;
    

    对于此查询,您需要具有类型为的集合属性。 此外,我还必须使用而不是
    TicketTuple
    (答案中引用),因为在处理没有票证的票证操作时,它给出了
    IllegalArgumentException
    (参数类型不匹配),我不知道您的模式中是否存在这种可能性

    EclipseLink JPA实现,Derby db

    在class
    Ticket
    中,您必须具有以下属性:

    @OneToMany(mappedBy = "ticket")
    private Collection<TicketAction> ticketActions;
    

    可以看到您的实体吗<代码>@OneToOne
    ?还有3-4行,您期望的结果是什么?是不是像
    true,1:false,2;false,3,true:4
    对于拉伸目标的
    分组方式
    :有一个集合或什么分组?更新了我的答案。您是否可以按票证检查此
    分组。票证id不为NULL
    ?您的第二次进近描述错误
    isNotNull
    返回一个
    谓词
    ,它实际上是一个
    表达式
    ,并且扩展了
    选择
    。问题在于布尔泛型类型与CriteriaQuery泛型类型定义的内容冲突。也许如果您发布了查询构造的其余部分,那么它将是一个更完整的定义……是否有可能看到您的实体<代码>@OneToOne
    ?还有3-4行,您期望的结果是什么?是不是像
    true,1:false,2;false,3,true:4
    对于拉伸目标的
    分组方式
    :有一个集合或什么分组?更新了我的答案。您是否可以按票证检查此
    分组。票证id不为NULL
    ?您的第二次进近描述为w
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);
    Root<Ticket> from = cq.from(Ticket.class);
    Join<Ticket, TicketAction> join = from.join("ticketActions", JoinType.LEFT);
    
    Expression<Boolean> caseHasAction = cb.<Boolean>selectCase()
          .when(cb.isNotNull(join.get("id")), true)
          .otherwise(false);
    
    cq.multiselect(
          caseHasAction.as(Boolean.class)
         ,from.get("id")
    );
    TypedQuery<Tuple> tq = em.createQuery(cq);
    
    for (Tuple tt : tq.getResultList()) {
        System.out.println("Res: " + tt.get(0) + " " + (tt.get(1) == null ? "null" : tt.get(1).toString()));
    }
    
    SELECT CASE WHEN (t0.ID IS NOT NULL) THEN 1 ELSE 0 END , t1.ID FROM TICKET t1 LEFT OUTER JOIN TICKET_ACTION t0 ON (t0.TICKET_ID = t1.ID)