HQL語句java
HQL(Hibernate Query Language)提供更加豐富靈活、更爲強大的查詢能力。數據庫
可設定WHERE數組
可進行投影查詢session
可分頁app
可分組函數
可作鏈接查詢測試
有聚合函數fetch
支持子查詢this
可動態綁定參數.net
先看一個HQL的基本用法,使用一對多多對一進行測試,Customer爲一的一端,Order爲多的一端,具體代碼,配置文件和數據庫數據以下:
<class name="cn.net.bysoft.model1.Customer" table="CUSTOMERS" batch-size="4"> <id name="id" type="integer" column="ID"> <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 --> <generator class="native"></generator> </id> <property name="name" type="string" column="NAME"></property> <!-- 一對多 --> <set name="orders" table="ORDERS" inverse="true" cascade="delete"> <key column="CUSTOMER_ID"></key> <one-to-many class="cn.net.bysoft.model1.Order" /> </set> </class>
<class name="cn.net.bysoft.model1.Order" table="ORDER_CUSTOMER"> <id name="id" type="integer" column="ID"> <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 --> <generator class="native"></generator> </id> <property name="name" type="string" column="NAME"></property> <!-- order.hbm.xml的多對一配置 --> <many-to-one name="customer" class="cn.net.bysoft.model1.Customer" column="CUSTOMER_ID" lazy="false" fetch="join"> </many-to-one> </class>
@Test public void testHql() { // 建立hql查詢對象 // 使用佔位符表明參數 String hql = "FROM Customer c WHERE c.id = ? OR c.name LIKE ? ORDER BY c.id DESC"; Query query = session.createQuery(hql); // 設置參數的值 query.setInteger(0, 1).setString(1, "%B%"); List<Customer> customers = query.list(); // 顯示結果 for (Customer customer : customers) { System.out.println(customer.getName()); } }
還能夠使用命名佔位符對WHERE條件的參數進行佔位:
@Test public void testHqlNameParam() { // 建立hql查詢對象 // 使用命名錶明參數 String hql = "FROM Customer c WHERE c.id = :id OR c.name LIKE :name ORDER BY c.name ASC"; Query query = session.createQuery(hql); // 設置參數的值 query.setInteger("id", 2).setString("name", "%C%"); List<Customer> customers = query.list(); // 顯示結果 for (Customer customer : customers) { System.out.println(customer.getName()); } }
也能夠使用實體做爲參數:
@Test public void testHqlEntityParam() { // 建立hql查詢對象 // 使用實體類做爲參數 String hql = "FROM Order o WHERE o.customer = ?"; Query query = session.createQuery(hql); // 設置參數的值 Customer customer = new Customer(); customer.setId(3); query.setEntity(0, customer); List<Order> orders = query.list(); // 顯示結果 for (Order order : orders) { System.out.println(order.getName()); } }
分頁查詢:
@Test public void testHqlPageQuery() { // 建立hql查詢對象 // 使用佔位符表明參數 String hql = "FROM Customer c"; Query query = session.createQuery(hql); // 當前頁 int pageNum = 3; // 每頁行數 int pageSize = 10; // 得到第一頁,也就是前十條 List<Customer> customers = query .setFirstResult((pageNum - 1) * pageSize) .setMaxResults(pageSize).list(); // 顯示結果 int i = 1; for (Customer customer : customers) { System.out.println("第" + (i++) + " 條:" + customer.getName()); } }
hql查詢語句也能夠定義在配置文件中,方便部署後的修改。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.net.bysoft.model1.Customer" table="CUSTOMERS" batch-size="4"> <id name="id" type="integer" column="ID"> <!-- 指定主鍵的生成方式,native是使用數據庫本地的方式 --> <generator class="native"></generator> </id> <property name="name" type="string" column="NAME"></property> <!-- 一對多 --> <set name="orders" table="ORDERS" inverse="true" cascade="delete"> <key column="CUSTOMER_ID"></key> <one-to-many class="cn.net.bysoft.model1.Order" /> </set> </class> <!-- 查詢語句定義 --> <query name="FindCustomerByName"> <![CDATA[ FROM Customer c WHERE c.name = :name ]]> </query> </hibernate-mapping>
@Test public void testHqlBySetQuery() { // 從配置文件中得到查詢的hql語句,並建立query對象 Query query = session.getNamedQuery("FindCustomerByName"); // 賦值參數 query.setString("name", "GG"); List<Customer> customers = query.list(); for (Customer customer : customers) { System.out.println(customer.getName()); } }
若是不須要查詢全部的列,值查詢幾個字段,也就是投影查詢,查詢結果爲List<Object[]>,字段的值封裝在Object[]數組中:
@Test public void testHqlByProperty() { Query query = session .createQuery("SELECT c.id, c.name FROM Customer c"); List<Object[]> customers = query.list(); for (Object[] customer : customers) { System.out.println(Arrays.asList(customer)); } }
若是以爲放到Object[]中不方便,也能夠把投影放入對象中保存,前提是對象有支持投影的構造函數:
@Test public void testHqlByPropertyEx() { Query query = session .createQuery("SELECT new Customer(c.id, c.name) FROM Customer c"); List<Customer> customers = query.list(); for (Customer customer : customers) { System.out.println(customer.getName()); } } public Customer(int id, String name) { super(); Id = id; this.name = name; }
能夠進行分組查詢統計:
@Test public void testHqlByGroupBy() { // 使用分組,查詢出每一個用戶有多少個訂單 String hql = "SELECT count(o.customer) FROM Order o GROUP BY o.customer"; Query query = session.createQuery(hql); List<Integer> orders = query.list(); // 顯示結果 System.out.println(orders); }
能夠使用迫切左外鏈接進行表與表的關聯,直接檢索出全部對象的數據,重複值能夠使用DISTINCT或者強轉HashSet解決:
@Test public void testHqlByLeftJoinFetch() { // 迫切左外鏈接 // String hql = // "SELECT DISTINCT c FROM Customer c LEFT JOIN FETCH c.orders"; String hql = "FROM Customer c LEFT JOIN FETCH c.orders"; Query query = session.createQuery(hql); List<Customer> customers = query.list(); customers = new ArrayList<Customer>(new LinkedHashSet<Customer>( customers)); for (Customer customer : customers) { for (Order order : customer.getOrders()) { System.out.println(customer.getName() + ":" + order.getName()); } } }
能夠使用普通左外鏈接進行表與表的關聯,當使用到關聯的對象的數據時在發送SQL查詢語句,去重複值如上解決:
@Test public void testHqlByLeftJoin() { // 左外鏈接 String hql = "SELECT DISTINCT c FROM Customer c LEFT JOIN c.orders"; Query query = session.createQuery(hql); List<Customer> customers = query.list(); // customers = new ArrayList<Customer>(new // LinkedHashSet<Customer>(customers)); for (Customer customer : customers) { for (Order order : customer.getOrders()) { System.out.println(customer.getName() + ":" + order.getName()); } } }
另外還有迫切內連接,普通內連接等,用法如上。
接着介紹一下QBC查詢方式,經過面向對象的方式建立查詢:
@Test public void testQBC() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); // 添加查詢條件 criteria.add(Restrictions.eq("name", "AA")); Customer customer = (Customer) criteria.uniqueResult(); System.out.println(customer.getName()); }
使用AND鏈接查詢條件:
@Test public void testQBCAnd() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); // 使用and鏈接查詢條件 Conjunction conjunction = Restrictions.conjunction(); conjunction.add(Restrictions.like("name", "B", MatchMode.ANYWHERE)); conjunction.add(Restrictions.eq("id", 2)); criteria.add(conjunction); Customer customer = (Customer) criteria.uniqueResult(); System.out.println(customer.getName()); }
使用OR鏈接查詢條件:
@Test public void testQBCOr() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); // 使用OR鏈接查詢條件 Disjunction disjunction = Restrictions.disjunction(); disjunction.add(Restrictions.like("name", "C", MatchMode.ANYWHERE)); disjunction.add(Restrictions.eq("id", 1)); criteria.add(disjunction); List<Customer> customers = criteria.list(); for (Customer customer : customers) { System.out.println(customer.getName()); } }
使用聚合函數:
@Test public void testQBCMax() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); // 使用聚合函數 criteria.setProjection(Projections.max("id")); System.out.println(criteria.uniqueResult()); }
使用分頁:
@Test public void testQBCByPageAndOrder() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); criteria.addOrder(org.hibernate.criterion.Order.desc("id")); // 使用分頁 int pageNum = 2; int pageSize = 10; criteria.setFirstResult((pageNum - 1) * pageSize).setMaxResults( pageSize); List<Customer> customers = criteria.list(); for (Customer customer : customers) { System.out.println(customer.getName()); } }
最後,介紹一下使用本地SQL進行增刪改等操做:
@Test public void testQBCByPageAndOrder() { // 建立QBC查詢 Criteria criteria = session.createCriteria(Customer.class); criteria.addOrder(org.hibernate.criterion.Order.desc("id")); // 使用分頁 int pageNum = 2; int pageSize = 10; criteria.setFirstResult((pageNum - 1) * pageSize).setMaxResults( pageSize); List<Customer> customers = criteria.list(); for (Customer customer : customers) { System.out.println(customer.getName()); } }
以上就是hibernate的HQL、QBC和本地SQL查詢檢索。