文章目录
1. Hibernate学习笔记四:hql语法学习
1.1. hql基本语法
- 查询所有
String hql = " from cn.zhangsan.domain.Customer ";//完整写法
String hql2 = " from Customer "; //简单写法
String hql3 = " from java.lang.Object ";//这个会查询所有对象内容会生成多个查询语句
Query query = session.createQuery(hql3);
List list = query.list();
System.out.println(list);
- 排序查询
String hql1 = " from Customer order by cust_id asc ";//简单写法升序
String hql2 = " from Customer order by cust_id desc ";//简单写法降序
Query query = session.createQuery(hql2);
List list = query.list();
System.out.println(list);
- 条件查询
String hql1 = " from Customer where cust_id =? ";//简单写法
String hql2 = " from Customer where cust_id = :id ";//简单写法(含临时名字)
Query query = session.createQuery(hql2);
//query.setParameter(0, 2l);
query.setParameter("id", 2l);//可以用序号代替参数位置也可以用临时名字代替
List list = query.list();
System.out.println(list);
- 分页查询
String hql1 = " from Customer ";//简单写法
Query query = session.createQuery(hql1);
//limit ?,?这种写法和sql原生语句相似,第一个?是从哪一条开始,第二个是到哪结束。
// (当前页数-1)*每页条数
query.setFirstResult(2);//表示从第几条开始
query.setMaxResults(2);//表示每页几条
List list = query.list();
System.out.println(list);
- 统计查询
String hql1 = " select count(*) from Customer ";//统计数量写法
String hql2 = " select sum(cust_id) from Customer ";//求和写法
String hql3 = " select avg(cust_id) from Customer ";//平均写法
String hql4 = " select max(cust_id) from Customer ";//最大写法
String hql5 = " select min(cust_id) from Customer ";//最小写法
Query query = session.createQuery(hql5);
Number number = (Number) query.uniqueResult();//uniqueResult当只有一个值时用这个
System.out.println(number);
- 投影查询
String hql1 = " select cust_name from Customer ";
String hql2 = " select cust_name,cust_id from Customer ";
String hql3 = " select new Customer(cust_id,cust_name) from Customer ";//注意在Customer实体类中也必须有该参数类型的构造函数。
Query query = session.createQuery(hql3);
List list = query.list();
System.out.println(list);
- 所谓的投影查询就是查询某个列的内容。投影即非全部,弄了个高大上的名字。
1.2. sql多表查询
- 交叉连接(笛卡尔积)
select * from A,B;
- 交叉连接会产生大量没用的查询,这个查询没什么意义。
- 隐式内连接
select * from A,B where b.id=a.id;
- 隐式连接通过添加判断条件免去了交叉连接的没用查询。
- 显式内连接比内连接块(两者结果相同)
select * from A inner join B on b.id=a.id;
- 左外连接
select * from A left [outer] join B on b.id=a.id;
- 右外连接
select * from A right [outer] join B on b.id=a.id;
- 左外连接后右外连接的区别,左外连接在连接时会以左表为准,左表有的,就会连接,如果右表没有就写null,同理右外连接也是这个道理。
- 外连接和内连接的区别:内连接中两个表若能连接到一起,必须两个表中都有该值,一个表如果没有,都不会连接。
1.3. hql多表查询
- 内连接
//注意最后的特殊之处,linkmens属于Customer表的属性。
String hql = " from Customer c inner join c.linkMens ";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for(Object[] arr : list){
System.out.println(Arrays.toString(arr));
}
- 迫切内连接
//HQL 迫切内连接 => 帮我们进行封装.返回值就是一个对象
String hql = " from Customer c inner join fetch c.linkMens ";//有个fetch
Query query = session.createQuery(hql);
List<Customer> list = query.list();
System.out.println(list);
- HQL左外连接
//HQL 左外连接 => 将连接的两端对象分别返回.放到数组中
String hql = " from Customer c left join c.linkMens ";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for(Object[] arr : list){
System.out.println(Arrays.toString(arr));
}
- HQL右外连接
//HQL 右外连接 => 将连接的两端对象分别返回.放到数组中.
String hql = " from Customer c right join c.linkMens ";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for(Object[] arr : list){
System.out.println(Arrays.toString(arr));
}
- 总之hql的多表查询不常用。
1.4. Criteria语法学习
- 基本查询
Criteria c = session.createCriteria(Customer.class);//直接获取的是class对象
List<Customer> list = c.list();
System.out.println(list);
-
条件语法—条件语法有很多自己的格式,可以在文档上查找。
-
分页查找
//首先创建Criteria对象,再调用该对象的方法。
Criteria c = session.createCriteria(Customer.class);
//limit ?,?
c.setFirstResult(0);
c.setMaxResults(2);
List<Customer> list = c.list();
System.out.println(list);
- 排序查找
//排序查找,先创建Criteria对象
Criteria c = session.createCriteria(Customer.class);
c.addOrder(Order.asc("cust_id"));
//c.addOrder(Order.desc("cust_id"));
List<Customer> list = c.list();
System.out.println(list);
- 统计查找
//先创建Criteria对象
Criteria c = session.createCriteria(Customer.class);
//设置查询目标
c.setProjection(Projections.rowCount());
List list = c.list();
System.out.println(list);
1.5. 离线查询
- 离线查询的思想:
由于软件开发的思想是:web层,service层,dao层,如果用一般的Criteria查询,每次都要给语句添加条件,设置查询内容等,造成了大量代码的书写。而离线查询的思路是在web层就创建好Criteria对象,并设置好查询的条件,在service层,建立session对象,并将查询内容封装到session对象中,开启事务,调用dao层。dao层调用session对象执行查询,并将获得的数据封装到list中。
- web层
//Service/web层
DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
dc.add(Restrictions.idEq(6l));//拼装条件(全部与普通Criteria一致)
System.out.println(list);
- service层
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//==========
//此处调用dao层
//==========
tx.commit();
session.close();
- dao层
Criteria c = dc.getExecutableCriteria(session);
List list = c.list();
1.6. lazy延迟加载机制
- 从上面分析,我们获取session都是通过get方法获取的,get方法获取有个特点就是获取就执行查询,返回结果,下面有一种方式lazy加载机制,lazy加载机制用load()方法不会立即执行查询,而是当用的时候才执行查询。不用不执行。
- lazy需要配置,lazy=“true”;在hibernate.hbm.xml中配置。调用的时候才加载数据。
1.7. 关联级别查询
- 集合关联查询
- 所谓集合关联查询是针对一对多中的一的,因为一包含一个set集合,所以称为集合关联查询。
- 两个属性:lazy=“true|false”;fetch="select|join|subselect"这三个属性值取笛卡尔积。
- lazy=“true”–表示只在调用时加载,否则不加载。
- fetch=“select”–单表查询,表示一次性查询所有,后面代码如果查询过了,就不必查询了。
- fetch=“join”–多表查询,一次性查询所有
- fetch=“subselect”–使用子查询加载集合
- 属性关联查询
- 所谓属性关联查询,是针对多对一中的多的,因为多中有一的外键属性。
- 两个属性:lazy=“true|false”;fetch=“select|join”;
- lazy=“true”;表示延迟加载,只有在调用时再加载。
- fetch="select"表示单表查询。
- fetch=“join”:表示多表查询。
- 总结:
结论:为了提高效率.fetch的选择上应选择select. lazy的取值应选择 true. 全部使用默认值.
- 批量抓取
-
所谓批量抓取是:当lazy的取值为true时,我们当获取某个集合对象时,由于是延迟加载,所以调用时都要发送sql语句,为了实现减少sql语句的发送,可以配置:batch-size=“n”;表示一次性获取几个。
-
batch-size: 抓取集合的数量为,抓取客户的集合时,一次抓取几个客户的联系人集合.
<set name="linkMens" batch-size="3" >
<key column="lkm_cust_id" ></key>
<one-to-many class="LinkMan" />
</set>