hibernate查询接口Query用法
hibernate的Session接口提供了get,load等按照id查询单个记录的方法,但是大多数时候,我们查询的是实体类的集合列表,这就需要用到复杂查询了,hibernate提供了类sql语句hql,他可以帮助我们编写复杂的查询语句,来做复杂的增删改查操作。这里介绍hibernate提供的Query接口用法。
Query接口的创建是通过Session来创建的,默认需要传入一个hql语句,比如sess.createQuery(hql)。如果我们需要在hql语句中传入参数,可以调用query.setParameter()等方法,可以做到动态传参。
另外Query提供的list,uniqResult,executeUpdate等方法,他们分别对应如下:
- list:查询列表
- uniqResult:查询唯一记录
- executeUpdate:执行修改或者删除操作
这里以hibernate-core-4.3.10.Final版本为例,为了简单,实体映射采用hibernate注解来实现,构建maven工程:
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
BaseEntity.java
package com.xxx.hibernate4.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class BaseEntity implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
protected Integer id;
@Column(name="createdate")
protected Date createDate;
@Column(name="modifydate")
protected Date modifyDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}
User.java
package com.xxx.hibernate4.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="xx_user")
public class User extends BaseEntity {
/**
*
*/
private static final long serialVersionUID = 1L;
private String username;
private String password;
@Column(length=11)
private String mobile;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password +
", mobile=" + mobile + ", age=" + age + ", id="
+ id + "]";
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///hibernate4?useUnicode=true&useSSL=false&characterEncoding=UTF-8</property>
<property name="connection.username">hadoop</property>
<property name="connection.password">hadoop</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQL57InnoDBDialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="com.xxx.hibernate4.entity.User"/>
</session-factory>
</hibernate-configuration>
准备工作做好了,直接上代码:
package com.xxx.hibernate4;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.xxx.hibernate4.entity.User;
@SuppressWarnings("deprecation")
public class SearchByHQL {
public static SessionFactory sessionFactory;
public static final ThreadLocal<Session> session = new ThreadLocal<>();
static {
try {
Configuration cfg = new Configuration().configure();
sessionFactory = cfg.buildSessionFactory();
} catch (HibernateException e) {
e.printStackTrace();
System.err.println("Initialize SessionFactory fail "+e);
}
}
public static Session getSession() {
Session sess = (Session)session.get();
if(sess==null) {
sess = sessionFactory.openSession();
session.set(sess);
}
return sess;
}
public static void closeSession() {
Session sess = (Session)session.get();
if(sess!=null) {
sess.close();
}
session.set(null);
sessionFactory.close();
}
@SuppressWarnings("unchecked")
public static void searchByHQL() {
Session sess = getSession();
String hql = "from User";
Query query = sess.createQuery(hql);
List<User> list = query.list();
for(User user:list) {
System.out.println(user);
}
closeSession();
}
public static void main(String[] args) {
searchByHQL();
}
}
准备数据, 数据库中的数据如下:
运行查询方法打印结果:
这个实例演示了一个最简单的Query查询列表方法,没有任何参数,直接调用,直接返回结果集。在一般的开发中,查询中带参数是最常见的做法,而且一个hql可能会带上多个参数。
Query给hql语句传参数,有两种方式,一种是使用"?"代替占位符,另一种是使用参数名代替(冒号+参数名),比如:username。目前,第一种使用"?"的方式已经被废弃了,我们来看具体的实现,以及运行打印的警告信息。
这里给出一个查询username以j开头的用户,条件拼接就是where username like 'j%'。
运行这个方法不会报错,但是会出现一个警告,意思是说这种传参方式已经废弃了:
WARN: [DEPRECATION] Encountered positional parameter near line 1, column 57 in HQL: [from com.xxx.hibernate4.entity.User where username like ?]. Positional parameter are considered deprecated; use named parameters or JPA-style positional parameters instead.
我们使用参数名占位的方式实现:
再次运行查询方法,就不会报警告提示了。
接下来,我们体验uniqResult()方法,这个是查询单个记录的。
运行结果打印:
接下来,我们体验分页方法,分页就是需要限制每页多少记录,以及从什么位置开始读取记录,Query接口提供了setFirstResult(int offset)方法和setMaxResult(int size)方法分别设置分页起始位置和分页大小。我们假定分页从第二页开始,每页10条记录。这样,我们的分页方法如下:
前面,我们准备了12条记录,按照测试方法的预期,我们需要查找第二页的10个记录,我们会得到ID分别为11和12的两条结果。运行查询方法打印结果: