在Hibernate中可以使用以下方式进行查询:
NativeSQL:不能实现跨数据库,本地的数据库语言
HQL:Hibernate自带的查询语言,将HQL语言根据方言进行转换SQL
EJBQL(JPQL1.0):可以认为是HQL的子集(这部分用的最多)
QBC(Query by Criteria):按条件查询
QBE(Query by Example):按样例查询
功能由下到上功能由弱到强
HQL
Hibernate提供了一种非常强大的查询语言HQL,其语法类似SQL,但是HQL是非常有意识的被设计为完全面向对象的查询(SQL提供的聚合函数更加丰富)。HQL除了Java类和属性的名称外,查询语句对大小写并不敏感。
首先我们定义几个实体
Category.java
package com.iflytek.QBC;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author xudongwang 2011-11-3 板块
*
* 板块与主题之间是一对多关系
*/
@Entity
public class Category {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Msg.java
package com.iflytek.QBC;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author xudongwang 2011-11-3 帖子回复
*
*/
@Entity
public class Msg {
private int id;
private String cont;
private Topic topic;
@ManyToOne
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCont() {
return cont;
}
public void setCont(String cont) {
this.cont = cont;
}
}
MsgInfo.java
package com.iflytek.HQL1;
/**
* @author xudongwang 2011-11-3
*
*/
public class MsgInfo { // VO或DTO Value Object一般用来装临时的值
private int id;
private String cont;
private String topicName;
private String categoryName;
public MsgInfo(int id, String cont, String topicName, String categoryName) {
super();
this.id = id;
this.cont = cont;
this.topicName = topicName;
this.categoryName = categoryName;
}
public String getTopicName() {
return topicName;
}
public void setTopicName(String topicName) {
this.topicName = topicName;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCont() {
return cont;
}
public void setCont(String cont) {
this.cont = cont;
}
}
Topic.java
package com.iflytek.HQL1;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author xudongwang 2011-11-3
*
*/
@Entity
public class Topic {
private int id;
private String title;
private Category category;
// private Category category2;
private Date createDate;
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@ManyToOne(fetch = FetchType.LAZY)
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
一、集合查询
Session session = sf.openSession();
session.beginTransaction();
// 这里使用的Query是org.hibernate.Query
// 同时这里需要写的类名而不要写表名
Query q = session.createQuery("from Category");
List<Category> categories = (List<Category>) q.list();
for (Category c : categories) {
System.out.println(c.getName());
}
session.getTransaction().commit();
session.close();
说明:通过Session的CreateQuery方法创建一个Query对象,它包含一个HQL查询语句。
调用Query的list()方法执行查询语句,该方法返回List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。
二、去重复排序
// distinct这里是和id的
Query q = session
.createQuery("select distinct c from Category c order by c.name desc");
三、传参“:”:
Query q = session
.createQuery("from Category c where c.id > :min and c.id < :max");
q.setParameter("min", 2);
q.setParameter("max", 8);
// 或
// q.setInteger("min", 2);
// q.setInteger("max", 8);
// 或
// Query q = session.createQuery(
// "from Category c where c.id > :min and c.id < :max")
// .setInteger("min", 2).setInteger("max", 8);//链式编程
List<Category> categories = (List<Category>) q.list();
四、传参“?”:
Query q = session
.createQuery("from Category c where c.id > ? and c.id < ?");
q.setParameter(0, 2).setParameter(1, 8);
// q.setParameter(1, 8);
五、分页:
Query q = session.createQuery("from Category c order by c.name desc");
q.setMaxResults(4);
q.setFirstResult(2);
// 这里所有使用参数的都可以使用链式编程
六、取对象指定字段:
// 上面去的都是对象,这里取的是字段,其返回值是Object类型的数组
Query q = session
.createQuery("select c.id, c.name from Category c order by c.name desc");
List<Object[]> categories = (List<Object[]>) q.list();
for (Object[] o : categories) {
System.out.println(o[0] + "-" + o[1]);
}
// 为什么不能直接写Category名,而必须写t.category
// 因为有可能存在多个成员变量(同一个类),需要指明用哪一个成员变量的连接条件来做连接
Query q = session
.createQuery("select t.title, c.name from Topic t join t.category c "); // join
for (Object o : q.list()) {
Object[] m = (Object[]) o;
System.out.println(m[0] + "-" + m[1]);
}
七、多表查询中的fetch
// 设定fetch type 为lazy后将不会有第二条sql语句
// 两张表联合查询
Query q = session.createQuery("from Topic t where t.category.id = 1");
如果Topic中:
@ManyToOne(fetch = FetchType.LAZY)
public Category getCategory() {
return category;
}
Hibernate: select topic0_.id as id2_, topic0_.category_id as category4_2_, topic0_.createDate as createDate2_, topic0_.title as title2_ from Topic topic0_ where topic0_.category_id=1
如果Topic中:
@ManyToOne
public Category getCategory() {
return category;
}
select topic0_.id as id2_, topic0_.category_id as category4_2_, topic0_.createDate as createDate2_, topic0_.title as title2_ from Topic topic0_ where topic0_.category_id=1 Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=?
八、构造方法查询
// VO Value Object
// DTO data transfer object
Query q = session
.createQuery("select new com.iflytek.QL1.MsgInfo(m.id, m.cont, m.topic.title, m.topic.category.name) from Msg m");
九、uniqueResult
Query q = session.createQuery("from Msg m where m = :MsgToSearch "); // 不重要,而QBE要比这个要灵活
Msg m = new Msg();
m.setId(1);
q.setParameter("MsgToSearch", m);
//如果有多个值抛错,如果有值且只有一个,返回一个object,如果没值,返回null
Msg mResult = (Msg) q.uniqueResult();
十、聚合函数
1、count:
Query q = session.createQuery("select count(*) from Msg m");
// count(*)返回的是long类型
long count = (Long) q.uniqueResult();
2、max、min、avg、sum:
Query q = session
.createQuery("select max(m.id), min(m.id), avg(m.id), sum(m.id) from Msg m");
Object[] o = (Object[]) q.uniqueResult();
System.out.println(o[0] + "-" + o[1] + "-" + o[2] + "-" + o[3]);
3、between and:
Query q = session.createQuery("from Msg m where m.id between 3 and 5");
4、in:
Query q = session.createQuery("from Msg m where m.id in (3,4, 5)");
5、is null 与 is not null:
Query q = session.createQuery("from Msg m where m.cont is not null");
6、is empty 与 is not empty:
Query q = session.createQuery("from Topic t where t.msgs is empty")
7、like:
// %表示0个或多个
Query q = session.createQuery("from Topic t where t.title like '%5'");
// _表示一个
Query q = session.createQuery("from Topic t where t.title like '_5'");
8、other
Query q = session.createQuery("select lower(t.title),"
+ "upper(t.title)," + "trim(t.title),"
+ "concat(t.title, '***')," + "length(t.title)"
+ " from Topic t ");
Query q = session.createQuery("select abs(t.id)," + "sqrt(t.id),"
+ "mod(t.id, 2)" + " from Topic t ");
Query q = session
.createQuery("select current_date, current_time, current_timestamp, t.id from Topic t");
Query q = session
.createQuery("from Topic t where t.createDate < :date");
q.setParameter("date", new Date());
Query q = session
.createQuery("select t.title, count(*) from Topic t group by t.title having count(*) >= 1");
Query q = session
.createQuery("from Topic t where t.id < (select avg(t.id) from Topic t)");
Query q = session
.createQuery("from Topic t where t.id < ALL (select t.id from Topic t where mod(t.id, 2)= 0) ");
// 用in 可以实现exists的功能
// 但是exists执行效率高
// t.id not in (1)
Query q = session
.createQuery("from Topic t where not exists (select m.id from Msg m where m.topic.id=t.id)");
// Query q =
// session.createQuery("from Topic t where exists (select m.id from Msg m where m.topic.id=t.id)")
十一、更新
Query q = session.createQuery("update Topic t set t.title = upper(t.title)");
q.executeUpdate();
十二、NamedQueries
// 在topic类上加上
// @NamedQueries( { @NamedQuery(name = "topic.selectCertainTopic", query
// = "from Topic t where t.id = :id") })
Query q = session.getNamedQuery("topic.selectCertainTopic");
q.setParameter("id", 5);
Topic t = (Topic) q.uniqueResult();
十三、NativeSQL
//createSQLQuery使用数据库本身的sql语言,所以里面的category是表名了
SQLQuery q = session.createSQLQuery("select * from category limit 2,4").addEntity(Category.class);
List<Category> categories = (List<Category>) q.list();