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查询检索。