关于JPA 2.0标准的一些基本问题

时间:2011-10-17 07:51:51

标签: hibernate jpa jpa-2.0 criteria-api

我今天发现了JPA 2.0 Criteria API,并希望了解它。刚刚通过一些例子,并试着去做。我有一个带有柱子的餐桌水果:

  • id,
  • name,
  • color,
  • 尺寸,
  • 味道。

常规的东西:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("fruitManager");
EntityManager em = emf.createEntityManager();

//get the criteria builder
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Fruit> c = cb.createQuery(Fruit.class);
  1. 如何使用条件构建以下查询:

    select id, name, color where name like 'XY%' and  color='orange'
    

    即。如何:

    • 只获取一些列,
    • 包括外卡搜索,
    • 包括AND,OR在哪里条件
  2. 此外,在获取实际数据之前,最好先计算结果。如何首先获取结果计数?
  3. 还有什么地方可以通过几种不同类型的SQL查询获得更多关于'Criteria'的例子吗?

2 个答案:

答案 0 :(得分:11)

首先,你操作实体,而不是表格,所以我将假设以下水果映射:

@Entity
public class Fruit {
    @Id int id;
    String name;
    String color;
}

当结果由单独的列组成时,查询的类型参数是Object [] .class(结果将是List of Object [])。其他可能性是使用元组。您可以使用以下内容构建您描述的查询。为了清楚地说明参数的类型,为Predicates和ParameterExpressions创建了中间变量。您还可以将其内联到查询创建中。

CriteriaQuery<Object[]> myquery = cb.createQuery(Object[].class);
Root<Fruit> root = myquery.from(Fruit.class);

ParameterExpression<String> nameParamExp = cb.parameter(String.class, "name");
ParameterExpression<String> colorParamExp = cb.parameter(String.class, "color");

Predicate namePredicate = cb.like(root.<String>get("name"), colorParamExp);
Predicate colorPredicate = cb.equal(root.get("color"), nameParamExp);

myquery.multiselect(root.get("id"), root.get("name"), root.get("color"))
        .where(cb.and(namePredicate, colorPredicate));

TypedQuery<Object[]> someFruits = em.createQuery(myquery);
someFruits.setParameter("name", "XY%");
someFruits.setParameter("color", "orange");

someFruits.getResultList();

您还可以通过内联所有内容来构建相同的查询:

myquery.multiselect(root.get("id"), root.get("name"), root.get("color"))
        .where(cb.and(
                cb.like(root.<String>get("name"), "XY%"),
                cb.equal(root.get("color"), "orange")));

或者使用Tuple作为结果类型:

CriteriaQuery<Tuple> myquery = cb.createQuery(Tuple.class);
Root<Fruit> root = myquery.from(Fruit.class);

myquery.select(cb.tuple(root.get("id").alias("id"),
                        root.get("name").alias("name"),
                        root.get("color").alias("color")))
       .where(cb.and(
                cb.like(root.<String>get("name"), "XY%"),
                cb.equal(root.get("color"), "orange")));

TypedQuery<Tuple> someFruits = em.createQuery(myquery);

for (Tuple t: someFruits.getResultList()) {
    //access your results by alias set in query instead of using array index
    Integer id = t.get("id", Integer.class);
    String name = t.get("name", String.class);
    String color = t.get("color", String.class);
}

如果您选择规范元模型,那么您需要在同一个包中跟随您的水果。您可以自己编写它,也可以使用某些工具生成(例如使用org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor)。第一次自己编写它是有道理的:

@StaticMetamodel(Fruit.class)
public abstract class Fruit_ {
    public static volatile SingularAttribute<Fruit, Integer> id;
    public static volatile SingularAttribute<Fruit, String> color;
    public static volatile SingularAttribute<Fruit, String> name;
}

然后你可以使用强类型参数并用以下代码替换前元组示例中的查询:

myquery.select(cb.tuple(root.get(Fruit_.id).alias("id"),
                        root.get(Fruit_.name).alias("name"),
                        root.get(Fruit_.color).alias("color")))
       .where(cb.and(
                cb.like(root.get(Fruit_.name), "XY%"),
                cb.equal(root.get(Fruit_.color), "orange")));

答案 1 :(得分:3)

标准API的基本教程可以在http://download.oracle.com/javaee/6/tutorial/doc/gjivm.html找到。

可以在http://www.altuure.com/2010/09/23/jpa-criteria-api-by-samples-part-i/找到示例,也可以查看第2部分。

相关问题