Hibernate初识4——hibernate查询及优化策略

一、HQL查询

    1、单表查询

1)全表查询

	@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User",User.class);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
ps: 为了避免空指针和内存溢出, User里面的toString方法最好不要有roles这个在外键关联的属性,

     2)别名查询

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select u from User u",User.class);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

     3)条件查询1

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User where id=6",User.class);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

     条件查询2

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User where id=?",User.class);
		query.setParameter(0, 6L);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

4)具名查询

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User where id=:id",User.class);
		query.setParameter("id", 6L);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

     5)分页查询

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User",User.class);
		query.setFirstResult(3);
		query.setMaxResults(3);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

     6)查询排序

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("from User order by id asc",User.class);
		List list = query.list();
		for(User user:list){
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
asc:升序,desc降序

     7)聚合查询

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select count(*) from User ",Long.class);
		Long result = query.uniqueResult();
		LOG.info(result);
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

     8)投影查询1

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select name,id from User ",Object[].class);
		List list = query.list();
		for (Object[] objects : list) {
			LOG.info(Arrays.toString(objects));
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

    投影查询2:注意创建对应的两个参数的构造方法

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select new com.starli.pojo.User(id,name) from User ",User.class);
		List list = query.list();
		for (User user : list) {
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

    2、多表查询

    1)内连接查询: inner join

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select u.name,r.name  from User u inner join u.roles r",Object[].class);
		List list = query.list();
		for (Object[] o : list) {
			LOG.info(Arrays.toString(o));
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

    2)左连接查询: left join

@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select u.name,r.name  from User u left join u.roles r",Object[].class);
		List list = query.list();
		for (Object[] o : list) {
			LOG.info(Arrays.toString(o));
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

    3)右连接查询:right join


@Test
	public void query(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Query query = session.createQuery("select u.name,r.name  from User u right join u.roles r",Object[].class);
		List list = query.list();
		for (Object[] o : list) {
			LOG.info(Arrays.toString(o));
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}

ps:内连接直接显示非null的,左连接以join左边的非null为主,右连接以右边的非null为主

二、QBC查询(使用Criteria)

       1)全表查询
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		List list = c.list();
		for (User user : list) {
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
       2)条件查询1
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		c.add(Restrictions.eq("id", 1L));
		User result = (User) c.uniqueResult();
		LOG.info(result);
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
        条件查询2
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		c.add(Restrictions.and(Restrictions.eq("id", 1L),Restrictions.like("name", "%小%")));
		User result = (User) c.uniqueResult();
		LOG.info(result);
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
     3)分页查询
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		c.add(Restrictions.like("name", "%小%"));
		c.setFirstResult(0);
		c.setMaxResults(3);
		List list = c.list();
		for (User user : list) {
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
     4)查询排序
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		c.addOrder(org.hibernate.criterion.Order.desc("id"));
		List list = c.list();
		for (User user : list) {
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
     5)聚合查询
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		c.setProjection(Projections.count("id"));
		Long result = (Long) c.uniqueResult();
		LOG.info(result);
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
     6)投影查询
@Test
	public void query2(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		Criteria c = session.createCriteria(User.class);
		ProjectionList list = Projections.projectionList();
		list.add(Property.forName("id"));
		list.add(Property.forName("name"));
		c.setProjection(list);
		List list2 = c.list();
		for (Object[] objects : list2) {
			LOG.info(Arrays.toString(objects));
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
三、本地sql查询
    
@Test
	public void query3(){
		Session session = HibernateUtil.openSession();
		Transaction bt = session.beginTransaction();getClass();
		NativeQuery query = session.createNativeQuery("select * from user",User.class);
		List list = query.list();
		for (User user : list) {
			LOG.info(user);
		}
		bt.commit();
		session.close();
		HibernateUtil.close();
	}
四、延迟加载
    延迟加载是为了减少程序和数据库的访问次数,提供程序的执行性能。

    延迟加载的执行机制:

    1)在查询一个对象的时候,不会到数据库查询对象的属性或者其关联的数据

    2)在需要使用到对象的属性或关联数据的才会去查询数据库!

1、类级别的延迟加载
 @Test
	    public void test1(){
	        
	        Session session = HibernateUtil.openSession();
	        Transaction tx = session.beginTransaction();
	        //get():get方法不支持类级别的延迟加载
	        User cust = session.get(User.class, 1L);//debug:此行查询了数据库
	        LOG.info(333);
	        System.out.println(cust.getName()); 
	        tx.commit();
	        session.close();       
	    }
@Test
	    public void test1(){
	        
	        Session session = HibernateUtil.openSession();
	        Transaction tx = session.beginTransaction();
	   
	        //load():load方法支持类级别的延迟加载
	        User cust = session.load(User.class, 1L);//debug:此行没有查询数据库
	        LOG.info(333);
	        System.out.println(cust.getName());//debug:此行查询了数据库
	        
	        tx.commit();
	        session.close();
	        
	    }

load():只有 load 方法才支持类级别的延迟加载

get():get 方法不支持类级别的延迟加载

使用 load() 方法的默认延迟加载策略是延迟加载,可以在配置文件中修改延迟加载策略

2、关联级别的延迟加载(以多对多为例)
 @Test
	    public void test1(){
	        
	        Session session = HibernateUtil.openSession();
	        Transaction tx = session.beginTransaction();
	        User cust = session.get(User.class, 1L);//debug:此行没有查询数据库
	        LOG.info(333);
	        System.out.println(cust.getRoles().size());//debug:此行查询了数据库
	        
	        tx.commit();
	        session.close();
	        
	    }
类级别默认使用延迟加载策略,如果不想使用延迟加载策略,那么可以在配置文件中修改延迟加载策略:Customer.hbm.xml
<set name="orders" cascade="all" inverse="true" lazy="false">
五、抓取策略

抓取策略,是为了改变 SQL 语句查询的方式,从而提高 SQL 语句查询的效率(优 化 SQL 语句)

可以设置以下三个值:fetch="select(默认值)|join|subselect"

1、查询一方单条记录
在Customer.hbm.xml中配置 fetch="select"会执行两条sql
 @Test
	    public void test1(){
	        
	        Session session = HibernateUtil.openSession();
	        Transaction tx = session.beginTransaction();
	        User cust = session.get(User.class, 1L);
	        LOG.info(333);
	        System.out.println(cust.getRoles().size());
	        
	        tx.commit();
	        session.close();
	        
	    }
配置  fetch="join"  会执行一条左外连接的sql语句。如果配置了join,那么延迟加载就会失效!


2、查询一方多条记录
需求:在查询多个一方(客户列表)的数据,关联查询多方(订单)的数据
     如果fetch的配置是select或join的时候,一共发出n+1条sql语句
     fetch="subselect": 使用子查询进行关联查询

3、查询多方记录
 
 fetch="select" : 默认情况,执行两条sql语句(支持延迟加载)
    fetch="join": 把两条sql合并成左外连接查询(效率更高)
   注意:如果配置了join,那么延迟加载就会失效!

六、整合连接池

1、maven项目中添加依赖,导入 c3p0 的整合相关包

                
   		    org.hibernate
   		    hibernate-c3p0
   		    5.2.10.Final
		
		
    		    com.mchange
    		    c3p0
    		    0.9.5.2
		
2、hibernate.cfg.xml中配置

org.hibernate.c3p0.internal.C3P0ConnectionProvider
10
20
3、测试connection是否是从c3p0中传来的
 @Test
	 public void test(){
		  Session session = HibernateUtil.openSession();
		  session.doWork(new Work(){

			@Override
			public void execute(Connection arg0) throws SQLException {
				LOG.info(arg0);
				
			}
			  
		  });
		  session.close();
	 }
七、二级缓存

​ Hibernate 的一级缓存:就是 Session 对象的缓存,而 Session 对象在每次操作之 后都会关闭,那么一级缓存就丢失!

结论 :一级缓存只用于一次业务操作内的缓存。

Hibernate 的二级缓存:就是 SessionFactory 的缓存,二级缓存和 SessionFactory 对象的生命周期是一致的,SessionFactory 不消耗,那么二级缓存的数据就不会 丢失!

结论:二级缓存可以用于多次业务操作的缓存。

注意的问题:

1)Hibernate 一级缓存默认是开启的,而且无法关闭。

2)Hibernate 二级缓存默认是关闭的,如果使用需要开启,而且需要引入第三 方的缓存工具,例如 EhCache 等。

1. 添加二级缓存需要实现jar包

jar包位置: hibernate解压目录下 lib/optional/ehcache下找到相关包!

maven项目,pom文件添加


   org.hibernate
   hibernate-ehcache
   5.2.10.Final
2. 配置二级缓存

在hibernate.cfg.xml中配置以下节点:property 节点 要放在 mapping 节点的上方

true
 
        org.hibernate.cache.ehcache.EhCacheRegionFactory
 
class-cache节点 要放在 mapping节点的下方
true
 
        org.hibernate.cache.ehcache.EhCacheRegionFactory
 


3、测试
package com.qfedu.hibernate.test;
import org.hibernate.Session;
import org.junit.Test;
import com.qfedu.hibernate.pojo.Customer;
import com.qfedu.hibernate.utils.HibernateUtil;
public class CacheLevelTwoTest {
    /**
     * 演示二级缓存
     */
    @Test
    public void test1(){
        
        Session session = HibernateUtil.openSession();
        
        //第1次操作
        Customer cust = session.get(Customer.class, 1L);
        System.out.println(cust.getName());
        
        //关闭session
        session.close();
        
        //第2次操作
        session = HibernateUtil.openSession();
        cust = session.get(Customer.class, 1L);
        System.out.println(cust.getName());
        
        session.close();
    }
}




    



你可能感兴趣的:(java,ee)