通过Hibernate查询信息
Hibernate提供了多种的查询方式来进行数据的获取。可以通过对象OID查询、导航查询、HQL语句查询,QBC查询,下面各自对这三种方式的查询步骤做出一个简单的汇总
下面的查询使用到了一些实体以及数据,数据实体包括代表消费者的实体Customer、代表收货地址的实力Address。二者为1对多的映射关系,下面是他们各自的值:
下面的例子将以上面的两个实体进行举例,为了节约篇幅,下面的代码片段都只写主要的,遵循下面的格式:
@Test
public void test(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.getCurrentSession();
transaction = sessnTransaction();
//举例所用代码片段
......
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
sessionFactory.close();
}
}
1、OID查询
就是之前所说到的通过get() / load()方法获取一个实体对象的方式,比较简单。
//在Customer实体所映射的表里面获取 id=1 的信息, 立即到对数据库进行查询。
Customer customer1 = (Customer) session.get(Customer.class, 1);
//在Customer实体所映射的表里面获取 id=2 的信息, 只有在下文使用到customer2非id的信息时候采取进行加载
Customer customer2 = (Customer) session.load(Customer.class, 2);
//上面两个方法的细节可以了解 Hibernate的延时加载机制,但都可以获取对象
2、对象导航查询
是在使用IOD获取到实体的基础上,再通过该实体获取其对应的N端集合或1端的实体对象。就本例而言,可以在获取一个消费者实体后,进而通过该实体获取消费者的所有地址集合(对应的N端集合)。反之,在先获取一个地址实体之后,也可以直接获取它所对应的消费者(1端实体)。具体示例代码如下:
//获取一个消费者
Customer customer = (Customer) session.get(Customer.class, 1);
//可以直接使用getXXX()方法将其收货地址集合获取到,XXX在建立二者的映射关系时候已经添加,此处为addressSet
Set<Address> addresses = customer.getAddressSet();
//后续操作
for(Address address : addresses){
System.out.println(address.toString());
}
上面演示的是1对多的映射关系,同样适用于多对多映射关系的对象导航查询,这里不再举例
3、HQL查询
HQL(Hibernate Query Language),Hibernate提供的查询语言,与sql语言类似。可以使用Query对象执行所构建的语句,Query对象可以从Session对象里面获取。通过HQL实现的查询主要包括:查询所有,条件查询,模糊查询,排序查询,分页查询投影查询,聚集函数查询,多表查询。下面将这些查询的简单示例列出:
3.1查询所有:
HQL语句格式: from 实体类类名。
示例:[from Address] 查询Address实体所对应的表的所有记录
Query query = session.createQuery("from Address");
//执行list()方法将按照上面所构建的语句获取结果,返回List
List<Address> list = query.list();
//后续操作
for(Address address : list){
System.out.println(address.toString());
}
3.2按条件查询:
HQL语句格式:from 实体类类名 where 实体类属性 = ? and 实体类属性n = ? \\
示例:[from Address where id = ?] 查询Address所对应的表里id = ?的行,具体值需要指定
上面所创建的语句需要使用Query对象提供的方法进行指定,可以使用setParameter(index, value)或者使用setXXX(index, value), XXX表示具体的包装类类型。与JDBC中填充PreparedStatement对象中预编译的SQL语句所使用的方法是类似的。
index表示第几个待填充的值,在Hibernate里面,第1个待填充的值索引为0,而不是1!这一点与PreparedStatement对象是不同的。而value指的是填充的值
Query query = session.createQuery("from Address where id < ?");
//query.setParameter(index, value)也可以使用该方法设置
query.setInteger(0,6);
List<Address> list = query.list();
//对list的后续操作......
3.3模糊查询
其实也算是条件查询的一种,like后跟得表达式有如下规则:
* % 代替任意个字符,相当于正则的 .+ * _ 代替一个字符,相当于正则的 . * [abc] 代替下列字符的任意单一字符, * [^abc]或者[!abc] 排除下列字符的任意单一字符, 同样与正则类似
HQL语句格式:from 实体类类名 where 实体类属性 like ?
示例[from Address where address like 北京市% ] 查询出地址以北京市开头的信息
Query query = session.createQuery("from Address where address like ? ");
//query.setParameter(index, value)也可以使用该方法设置
query.setString(0, "北京市%");
List<Address> list = query.list();
3.4升/降序查询
HQL语句格式:from 实体类类名 [条件] order by 实体类属性 [desc/asc]
示例:[from Address order by id desc] 对Address对应的表按id进行降序排列,asc升序排列
3.5分页查询
分页不是从HQL语句进行调整,而是通过Query对象的方法:setFirstResult(int) / setMaxResults(int)方法进行,前者设置分页开始的位置,后者设置每一页的记录数。
Query query = session.createQuery("from Address");
//从第4个位置位置开始查询,查询一页,一页数量为2
query.setFirstResult(3);
query.setMaxResults(2);
3.6投影查询
HQL语法格式: select 实体属性 from 实体类类名 [条件] [排序]
示例:[select address from Address]查询出Address实体对应表的address列的所有信息
3.7聚集函数
HQL语法格式:select 函数 from 实体类类名
示例:[select count(*) from Address]查询出Address对应表的信息总条数
在获取单列的信息时候,可以使用uniqueResult()方法获取结果而不是使用list()方法。
Query query = session.createQuery("select count(*) from Address");
Object obj = query.uniqueResult();
//转换为int以便后续使用
System.out.println(Integer.parseInt(obj+""));
3.8内连接
HQL语法格式:from 实体类类名 自定义实体类名称 inner join 自定义实体类名称.所映射另一端实体在本实体的属性
示例:在Customer这个实体中,他所映射的另一端的实体就是与它具有映射关系的Address实体,
而所映射的Address实体保存在Customer实体里面的addressSet集合。所以HQL可以写为:
from Customer c inner join c.addressSet
返回的list内部包含的是数组,要想将其内部包含的是对象,需要使用迫切内连接
Query query = session.createQuery("from Customer c inner join c.addressSet");
List list = query.list();
for(Object temp : list){
Object[] arr = (Object[]) temp;
//索引0包含了Customer的信息,索引1包含了addressSet的信息
System.out.println(arr[0]);
}
3.9迫切内连接
HQL语法格式与内连接基本相同,不过是在join关键字后面加入了又一关键字fench,使用方式与内连接相同
返回对的list集合内部包含的是对象的形式,不再是数组
4.QBC查询
使用hql查询的时候,需要在里面指定执行的名称,而使用QBC的时候,可以直接调用其中的方法来执行特定的功能。执行的功能与HQL基本相同。
执行QBC查询主要使用到了Criteria对象,构建一个新的Criteria对象,并指定class对象以决定操作的实体。
构建一个Criteria对象来操作Addres实体对应的表:Criteria criteria = session.createCriteria(Address.class);
4.1查询所有
QBC在构建完毕之后默认就是查询全表的,所以此时直接调用list()方法就可以得到映射表的所有信息
4.2条件查询
在构建完一个Criteria对象之后,默认查询全部,可以使用Criteria对象的add()方法为其添加查询条件。查询条件可以使用Restrictions对象的静态方法进行构造,传递相应的值构造一个条件添加到Criteria对象里面。常用的条如下,他们都是静态方法,可以直接调用生成条件并添加:
每个方法都要求传递一些值,就Restrictions.eq(propertyName, value)方法来讲,要求传入设置相等的属性名称,并传递等于的值,使用实例如下,具体的参数可以查看Hibernate的API说明
Criteria criteria = session.createCriteria(Address.class);
//为Criteria对象添加条件 id = 2
criteria.add(Restrictions.eq("id", 2));
//查询Address对应表中id = 2 的信息
List<Address> list = criteria.list();
//.......
4.3排序查询
与条件查询类似,排序查询也需要使用addOrder(Order order)方法传递一个表示排序规则的对象Order(注意是hibernate包下的对象),使用比较简单:
Criteria criteria = session.createCriteria(Address.class);
//设置addOrder方法进行排序,传入Order对对象,选择其排序方式并指定排序所依据的属性,升序为Order.asc(propertyName)
criteria.addOrder(Order.desc("id"));
List<Address> list = criteria.list();
4.4分页查询
与HQL语言的分页查询类似,也是使用setFirstResult()方法以及setMaxResults()方法,进而再次获取查询的集合。
4.5聚合函数查询
还是需要传递一个标识聚合函数的对象,与分页查询,排序查询是类似的。只不过它传递的是Projection对象,代表一个聚合函数,使用Criteria对象的setProjection()对象将设置的聚合函数添加。与条件查询一样,也有一个类专门生产聚合函数对象:Projections类包含一系列生成Projection聚合函数的方法,具体的可以参见Hibernate API
4.6离线查询
了解不多,只知道不是通过Session对象生成的,便于使其作为参数进行传递。
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Address.class);
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
criteria.add(Restrictions.eq("id", 2));
List<Address> list = criteria.list();
for(Address address : list){
System.out.println(address);
}