使用Hibernate的JPA 2.0标准查询

JPA 2.0中引入了条件查询 。 借助条件查询,您可以以类型安全的方式编写查询。 在进行标准查询之前,开发人员必须通过构建基于对象的查询定义来编写查询。 构建查询时,可能会出现语法错误的情况。 条件查询API提供了创建具有编译时安全性的结构化和嵌套查询的功能。 进入有关标准查询的更多理论可能不是一个好主意,因为可以在网上找到大量相同的页面。 让我们举一个简单的例子来了解使用条件查询的查询。 在这篇文章中,我将Hibernate作为JPA 2.0的供应商来展示Criteria Query的示例。
在深入探讨标准查询之前,让我们考虑一下可以表示为实体的数据库表和相应的Java类:

数据库表:

例如,下面有两个数据库表:

    1. 状态[stateId,stateName]
    2. 城市[cityId,stateId(FK#),CityName]
我们要获取特定州的城市列表,在该州中,城市名称应从“ M”开始,城市列表应按升序排列。 如果我们考虑简单的本机SQL,则如下所示:
Select * from City c, State s where c.stateId = s.stateId and c.stateId = ? and c.cityName like "M%" order by c.cityName

JPA实体:

以下是配置为JPA实体以表示州和城市表的两个Java类。 这些也可以使用逆向工程工具生成。

STATE表的Java实体

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.Date;
import java.util.Set;
import javax.persistence.SequenceGenerator;

@Entity
@Table(name="STATE")
@SequenceGenerator(sequenceName="STATE_SEQ",name="STATE_SEQ_GEN")
public class State {
    private Long stateId;
    private String stateName;
    private Set citySet;
    @Id
    @Column(name="stateId")
    @GeneratedValue(generator="STATE_SEQ_GEN",strategy=GenerationType.SEQUENCE)
    public Long getStateId;() {
       return stateId;
    }
    public void setId(long stateId) {
        stateId = stateId;
    }

   @Column(name="stateName")
    public String getStateName() {
        return stateName;
    }
    public void setStateName(String stateName) {
        this.stateName = stateName;
    }
    public void setCitySet(Set citySet)
        this.citySet= citySet;
    }

    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="state")
    public Set getCitySet() {
        return citySet;
    }
}

CITY表的Java实体

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="CITY")
@SequenceGenerator(sequenceName="CITY_SEQ",name="CITY_SEQ_GEN")
public class City {
    private Long cityId;
    private String cityName;
    private State state;

    public void setId(long cityId) {
        this.cityId = cityId;
    }
 @Id
 @Column(name="CityId")
 @GeneratedValue(generator="CITY_SEQ_GEN",strategy=GenerationType.SEQUENCE)
    public Long getCityId() {
        return cityId;
    }
    @Column(name="CityName")
    public void setContent(String cityName) {
        this.cityName = cityName;
    }
    public String getCityName() {
        return cityName;
    }
    public void setState(State state) {
        this.state = state;
    }
   @ManyToOne(fetch =  FetchType.LAZY)
   @JoinColumn(name = "STATEID", nullable = false)
    public state getState() {
        return state;
    }
}

值对象(PO​​JO):

以下是两个值对象。 借助条件查询,您可以直接从结果数据映射值对象。 您无需编写代码即可将结果数据从实体类复制到value对象。 这确实是条件查询中令人兴奋的功能。
public class StateVO {
    private Long stateId;
    private String stateName;
    private Set cityVOSet;
   // All getter setters
 }
public class CityVO {
    private Long cityId;
    private String cityName;
    private StateVO stateVO;
    public CityVO( Long cityId, String cityName){
                  this.cityId=cicityId;
                  this.cityName=cityName;
    }
    // All getter setters
}

DAO实施:

现在是时候使用标准查询来获取数据了。 我们将公开一个将输入参数作为StateVO并返回CityVO列表的方法。
import javax.persistence.EntityManager;
       import javax.persistence.EntityManagerFactory;
       import javax.persistence.Persistence;
       public class StateCityDAOImpl{
       
       public List getCityList(StateVO searchStateVO)  {
         // Get the entity manager instance
         EntityManagerFactory emf = Persistence.createEntityManagerFactory("StateCityService");
         EntityManager entityManager= emf.createEntityManager();
     
         // Get the criteria builder instance from entity manager
        final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
       
       // Create criteria query and pass the value object which needs to be populated as result
        final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(CityVO.class);
     
        // Tell to criteria query which tables/entities you want to fetch
        // To join the City and State tables, we need to write below code
        final Root stateRoot = criteriaQuery.from(State.class);
        final Root cityRoot = criteriaQuery.from(City.class);
   
       // Time to define where clause in terms of Predicates
        // This list will contain all Predicates (where clauses)
        List criteriaList = new ArrayList();
    
       // Note: Ensure that whatever string you are passing in root variables
        // It should be matched with variables' name in entity classes
     
        // [1] where condition: State.StateId = City.StateId
        Predicate predicate1 = criteriaBuilder.equal(
                cityRoot. get("state"). get("stateId"),
                stateRoot.  get("stateId"));
        criteriaList.add(predicate1);

        // [2] where condition: City.StateId = ?
        if (searchStateVO.getStateId() != null) {
           Predicate predicate2= criteriaBuilder.equal(
                    cityRoot. get("state"). get("stateId"),
                    searchStateVO.getStateId());
            criteriaList.add(predicate2);
        }

        // [3] where condition: City.cityName like 'M%'
        Predicate predicate3
                  = criteriaBuilder.like(criteriaBuilder.upper(cityRoot. get("cityName")),
                      "M%");
            criteriaList.add(predicate3);  
     
        // This statement maps your CityVO with result data
        // You have to have a custom constructor in CityVO  (see above) to populate the result data   
        criteriaQuery.select(criteriaBuilder.construct(CityVO.class, cityRoot. get("cityId"),
                cityRoot. get("cityName")));
 
        // Pass the criteria list to the where method of criteria query
        criteriaQuery.where(criteriaBuilder.and(criteriaList.toArray(new Predicate[0])));

        // Order by clause based on city names
        criteriaQuery.orderBy(criteriaBuilder.asc(cityRoot. get("cityName")));

        // Here entity manager will create actual SQL query out of criteria query
        final TypedQuery query = entityManager.createQuery(criteriaQuery);
      
        // This code can be used to define the row range to fetch the result
        /* if (CitySize != 0) {
            query.setFirstResult(startIndex); // starting row index
            query.setMaxResults(endIndex); //  end row index
       }*/
        return query.getResultList();
  }
现在我们有了CityVO清单作为您的答案。 我们可以根据上述要求访问相应的城市名称。
虽然,使用条件查询编写查询可能有点笨拙,但是一旦使用方便,您就会喜欢“条件查询”。

参考:我们的JCG合作伙伴 Narendra Verma在NS.Infra博客上的《 使用Hibernate进行JPA 2.0标准查询》

翻译自: https://www.javacodegeeks.com/2013/04/jpa-2-0-criteria-query-with-hibernate.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值