Java框架 Hibernate入门笔记二 使用HQL&Criteria&标准SQL
之前已经学过了如何用Hibernate做简单的CRUD操作, 但是SQL语句其实有很多功能, 光有之前的简单crud可能是不够的, 比如之前的:
Retrieve查询是只能根据主键(id)来查询
一.通过HQL进行查询
这是一种类似于SQL的语法;
比如可以这样做:
import Entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import java.util.List;
public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
String name = "client";
Query q = s.createQuery("from User a where a.name like :name");
q.setParameter("name",name+"%");
List<User> list = q.list();
for(User i : list){
System.out.println(i);
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
之前的HQL语法和我这里写的有些不同, 因为现在的HQL可以使用JPA-style来符合java persistence api, 有两种写法:
一种是像我上面写的, 使用命名的方式3:
Query q = s.createQuery("from User a where a.name like :name");
q.setParameter("name",name+"%");
也可以这样, 使用占位符:
Query q = s.createQuery("from User a where a.name like ?0");
q.setParameter(0,name+"%");
以前的HQL语法现在已经过时如果用这样的语法:
Query q = s.createQuery("from User a where a.name like ?");
q.setString(0,name+"%");
可能会提示org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported;
最好使用新标准的JPA规范;
二.使用CRITERIA进行查询
第一个问题是什么事Criteria, 为什么要用它:
Criteria API,它为 Java 语言带来了一种独特的能力:开发一种 Java 编译器可以在运行时验证其正确性的查询。Criteria API 还提供一个能够在运行时动态地构建查询的机制。
Criteria可以保证查询的输出结果是对应于某个实体类的, 而不是运行之后才发现类型不匹配;
Criteria API 的最大优势之一就是禁止构造语法错误的查询。
可以使用Criteria进行查询:
import Entity.User;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;
import java.util.List;
public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
String name = "client";
Criteria c = s.createCriteria(User.class);
c.add(Restrictions.like("name",name+"%"));
List<User> list = c.list();
for(User i : list){
System.out.println(i);
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
查询结果大概是这样:
但是可以看到, 这种方法似乎已经过时了;
好像新的做法大概是这样的:
import Entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;
public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
String name = "client";
CriteriaBuilder crb= s.getCriteriaBuilder();
CriteriaQuery<User> crq=crb.createQuery(User.class);
Root<User> root=crq.from(User.class);
crq.select(root);
crq.where(crb.like(root.get("name"),name));
List<User> list = s.createQuery(crq).getResultList();
for(User i : list){
System.out.println(i);
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
流程大概是这样:
1.从Hibernate获得一个Session
2.从Session中获得一个用于Criteria的builder然后创建一个对User的查询Query
3.设置query的查询内容
4.获得ResultList
这里对于设置query的查询内容部分代码可以简单理解一下;Root<User> root=crq.from(User.class);
这里就相当于sql中的from user
crq.select(root);
表示把root用于select查询crq.where(crb.like(root.get("name"),name));
表示给query添加一个where的条件(限制);
在Hibernate中也可以:
三.使用标准的sql语句进行查询
代码大概是这样:
import Entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import java.util.List;
public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
String name = "client";
String sql = "select * from user where name like \'"+name+"%\'";
Query q = s.createSQLQuery(sql);
List<Object[]> list = q.list();
for(Object[] i : list){
for(Object j : i){
System.out.println(j);
}
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
注意是s.createSQLQuery(sql);
要指定是SQL查询;
查询结果大概是这样:
要注意的是这里的返回结果是一个Object[]数组的List, 数组里面存放着表中的数据;
因为标准SQL语句有可能返回各种各样的结果,比如多表查询,分组统计结果等等。 不能保证其查询结果能够装进一个Product对象中,所以返回的集合里的每一个元素是一个对象数组。 然后再通过下标把这个对象数组中的数据取出来。