关于JPA 2.0标准的一些基本问题 [英] Some basic questions on Criteria from JPA 2.0

查看:77
本文介绍了关于JPA 2.0标准的一些基本问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天发现了JPA 2.0 Criteria API,并且想要学习它。刚刚通过一些例子,并尝试做手。我有一个列表水果:


  • id,

  • name,

  • 颜色,
  • 尺寸,
  • 口味。

  • 常规的东西:

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

    //获取标准生成器
    CriteriaBuilder cb = em.getCriteriaBuilder();

    CriteriaQuery<水果> c = cb.createQuery(Fruit.class);




    1. 如何使用条件构建以下查询:

       选择ID,名称,颜色名称,如'XY%'和color ='orange'

      即,如何:


      • 仅提取一些列,
      • 包含通配符搜索,

      • 包括AND,OR where条件。


    2. 另外,在获取实际数据之前,最好先计算结果数。我怎样才能首先获得结果数?

    还有什么地方可以在'Criteria'上得到更多的例子,类型的SQL查询?首先,你操作实体,而不是表格,所以我将假定以下映射为Fruit:

      @Entity 
    public class Fruit {
    @Id int id;
    字符串名称;
    字符串颜色;





    $ b当结果由不同的列组成时,查询的类型参数是Object []。类(结果将是对象[]的列表)。其他可能性是使用Tuple。您可以使用以下内容构建查询。为了明确参数类型,为Predicates和ParameterExpressions创建中间变量。您可以将这些内联内联到查询创建中。

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

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

    谓词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),橙子)));

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

      CriteriaQuery中<元组GT; myquery = cb.createQuery(Tuple.class); 
    Root<水果> 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()){
    //通过在查询中设置别名来访问结果,而不是使用数组索引
    Integer id = t.get id,Integer.class);
    String name = t.get(name,String.class);
    String color = t.get(color,String.class);



    $ b $ p
    $ b

    如果你使用规范元模型,那么你需要在同一个包中使用以下类:你的水果。这取决于你自己编写或使用某​​种工具生成(例如使用org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor)。第一次有必要自己编写它:

      @StaticMetamodel(Fruit.class)
    public abstract class Fruit_ {
    public static volatile SingularAttribute< Fruit,Integer> ID;
    public static volatile SingularAttribute< Fruit,String>颜色;
    public static volatile SingularAttribute< Fruit,String>名称;
    }

    然后,您可以使用强类型参数并将前一个元组中的查询替换为以下内容:

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


    I discovered JPA 2.0 Criteria API today and want to learn it. Just went through some examples and try to do a hands on. I have a table fruit with columns:

    • id,
    • name,
    • color,
    • size,
    • taste.

    The regular stuff:

    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. How will the following query get built using criteria:

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

      I.e. how to:

      • fetch only some columns,
      • include wild card search,
      • include AND, OR where conditions.

    2. Also, its always better to get count of the result first before fetching the actual data. How can I fetch the result count first?

    Also Is there any place where I can get more examples on 'Criteria' with several different kinds of SQL queries?

    解决方案

    First, you operate to Entities, not to tables, so I will assume following mapping for Fruit:

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

    When result consists of separate columns, type argument to query is Object[].class (result will be List of Object[]). Other possibility is to use Tuple. You can build query you described with following. Just for being clear about type of argument for the sake of example, intermediate variables are created for Predicates and ParameterExpressions. You can also inline those to the query creation.

    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();
    

    You can also build same query by inlining everything:

    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")));
    

    Or use Tuple as result type:

    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);
    }
    

    If you go for canonical metamodel, then you need following class in same package with your fruit. It is up to you do you write it by yourself or generate with some tool (for example with org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor). First time it makes sense to write it by yourself:

    @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;
    }
    

    Then you can go for strongly typed arguments and replace query in former tuple example with following:

    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")));
    

    这篇关于关于JPA 2.0标准的一些基本问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆