hibernate的N+1条SQL查询问题--Iterate和list

hibernate使用session.createQuery(hql)查询数据的时候,有两种查询方式

1、session.createQuery(hql).list()

2、session.createQuery(hql).iterate()

通过项目案例来简单了解下,项目结构如下:

hibernate的N+1条SQL查询问题--Iterate和list_第1张图片

Book实体类代码

public class Book {
	private int id;
	private String name;
	private double price;
	private String author;
	private Date pubDate;
	public Book() {
	}
	public Book(String name, double price) {
		super();
		this.name = name;
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", price=" + price
				+ ", author=" + author + ", pubDate=" + pubDate + "]";
	}
	//省略get/set
}
Book.hbm.xml配置文件

  
      
          
              
          
          
          
          
          
      
 

HibernateTest测试类

public class HibernateTest {
	@Test
	public void testCreateDB(){
		Configuration cfg=new Configuration().configure();
		SchemaExport se=new SchemaExport(cfg);
		se.create(true, true);
	}
	@Test
	public void testSave(){
		Session session=HibernateUtil.getSession();
		Transaction tx=session.beginTransaction();
		Book book=new Book();
		book.setName("读者");
		book.setPrice(21.5);
		book.setAuthor("读者出版传媒有限公司");
		book.setPubDate(new Date());
		Book book1=new Book();
		book1.setName("蓝血人");
		book1.setPrice(50);
		book1.setAuthor("卫斯理");
		book1.setPubDate(new Date());
		Book book2=new Book();
		book2.setName("傲慢与偏见");
		book2.setPrice(80);
		book2.setAuthor("简.奥斯丁");
		book2.setPubDate(new Date());
		Book book3=new Book();
		book3.setName("中国历史");
		book3.setPrice(21.5);
		book3.setAuthor("人民");
		book3.setPubDate(new Date());
		
		session.save(book);
		session.save(book1);
		session.save(book2);
		session.save(book3);
		tx.commit();
		HibernateUtil.closeSession();
	}
	@Test
	public void testList(){
		Session session=HibernateUtil.getSession();
		Transaction tx=session.beginTransaction();
		//list一次性将所有数据查出
		List list=session.createQuery("from Book").list();
		for(Book book:list){
			System.out.println("书名:"+book.getName());
		}
		tx.commit();
		HibernateUtil.closeSession();
	}
	@Test
	public void testIterate(){
		Session session=HibernateUtil.getSession();
		Transaction tx=session.beginTransaction();
		//iterate先把所有数据的id查询,然后当需要某条记录时,再根据id去查询详细信息
		Iterator iter=session.createQuery("from Book").iterate();
		for(;iter.hasNext();){
			Book book=iter.next();
			System.out.println("书名:"+book.getName());
		}
		tx.commit();
		HibernateUtil.closeSession();
	}
}
HibernateUtil类

public class HibernateUtil {
	private static Configuration cfg=null;
	private static SessionFactory factory=null;
	private static Session session=null;
	static{
		cfg=new Configuration().configure();
		factory=cfg.buildSessionFactory(new StandardServiceRegistryBuilder()
		        .applySettings(cfg.getProperties()).build());
	}
	public static Session getSession(){
		if(factory!=null)
			return session=factory.openSession();
		factory=cfg.buildSessionFactory(new StandardServiceRegistryBuilder()
		        .applySettings(cfg.getProperties()).build());
		return session=factory.openSession();
	}
	public static void closeSession(){
		if(session!=null && session.isOpen())
			session.close();
	}
}

运行测试类testCreateDB生成数据库表,运行testSave向表中添加数据。

执行testList,打印信息如下

Hibernate: 
    select
        book0_.id as id1_0_,
        book0_.author as author2_0_,
        book0_.book_name as book_nam3_0_,
        book0_.price as price4_0_,
        book0_.pubDate as pubDate5_0_ 
    from
        book book0_
书名:读者
书名:蓝血人
书名:傲慢与偏见
书名:中国历史
执行testIterate,打印信息如下

Hibernate: 
    select
        book0_.id as col_0_0_ 
    from
        book book0_
Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.author as author2_0_0_,
        book0_.book_name as book_nam3_0_0_,
        book0_.price as price4_0_0_,
        book0_.pubDate as pubDate5_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
书名:读者
Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.author as author2_0_0_,
        book0_.book_name as book_nam3_0_0_,
        book0_.price as price4_0_0_,
        book0_.pubDate as pubDate5_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
书名:蓝血人
Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.author as author2_0_0_,
        book0_.book_name as book_nam3_0_0_,
        book0_.price as price4_0_0_,
        book0_.pubDate as pubDate5_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
书名:傲慢与偏见
Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.author as author2_0_0_,
        book0_.book_name as book_nam3_0_0_,
        book0_.price as price4_0_0_,
        book0_.pubDate as pubDate5_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
书名:中国历史

总结:

list()和iterate()区别

1、返回的类型不同,list()返回List,iterate()返回Iterator

2、获取方式不同,list会一次性将数据库中的信息全部查询出,iterate会先把所有数据的id查询出来,然后真正要遍历某个对象的时候先到缓存中查找,如果找不到,以id为条件再发送一条sql到数据库,这样如果缓存中没有数据,则查询数据库的次数为n+1

3、iterate会查询2级缓存,list只会查询一级缓存

4、list中返回的List中每个对象都是原本的对象,iterate中返回的对象是代理对象。(debug可以发现)








你可能感兴趣的:(hibernate)