1+N就是在hibernate中第一次查一个所需要的表的内容,他会把别的相关表的内容也查询一遍。


解决办法有三种:

1,设置LAZY。

2,借鉴createCriteria的查询语句,from Topic t left join fetch t.category c,通过join fetch来屏蔽多于查询。

3,将多次查询整成一次查询。给多于表加上BatchSize注解。这种方法并没有解决问题,只是相对来说优化了一点。


解决办法3的写法:

package com.bjsxt.hibernate;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import org.hibernate.annotations.BatchSize;

@Entity

//@BatchSize(size=5)//加上BachtSize注解,如此,一次会查询五条相关内容

public class Category {

    private int id;

    private String name;

    @Id

    @GeneratedValue

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

}




测试类:

import java.util.Date;

import java.util.List;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

public class HibernateQLTest {

    private static SessionFactory sf;


    @BeforeClass

    public static void beforeClass() {

        sf = new AnnotationConfiguration().configure().buildSessionFactory();

    }

    @AfterClass

    public static void afterClass() {

        sf.close();

    }


    @Test

    public void testSchemaExport() {

        new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);

    }


    @Test

    public void testSave() {

        Session session = sf.openSession();

        session.beginTransaction();


        for(int i=0; i<10; i++) {

            Category c = new Category();

            c.setName("c" + i);

            Topic t = new Topic();

            t.setCategory(c);

            t.setTitle("t" + i);

            t.setCreateDate(new Date());

            session.save(c);

            session.save(t);

        }


        session.getTransaction().commit();

        session.close();

    }


    //N+1

    @Test

    public void testQuery1() {

        Session session = sf.openSession();

        session.beginTransaction();

        //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();

        List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list();



        for(Topic t : topics) {

            System.out.println(t.getId() + "-" + t.getTitle());

        }

        session.getTransaction().commit();

        session.close();


    }


    @Test

    public void testQuery2() {

        Session session = sf.openSession();

        session.beginTransaction();

        //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();//关联关系不设lazy也不会全部查询,因为使用的是关联表方式

        List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list();//关联关系不设lazy会全部查询



        for(Topic t : topics) {

            System.out.println(t.getId() + "-" + t.getTitle());

            System.out.println(t.getCategory().getName());

        }

        session.getTransaction().commit();

        session.close();


    }


    //@BatchSize

    @Test

    public void testQuery3() {

        Session session = sf.openSession();

        session.beginTransaction();

        //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();

        List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list();


        for(Topic t : topics) {

            System.out.println(t.getId() + "-" + t.getTitle());

            System.out.println(t.getCategory().getName());

        }

        session.getTransaction().commit();

        session.close();


    }

    //join fetch

    @Test

    public void testQuery4() {

        Session session = sf.openSession();

        session.beginTransaction();

        //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();

        List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list();


        for(Topic t : topics) {

            System.out.println(t.getId() + "-" + t.getTitle());

            System.out.println(t.getCategory().getName());

        }

        session.getTransaction().commit();

        session.close();


    }

    public static void main(String[] args) {

        beforeClass();

    }

}