1 hibernate 缓存

  1.1 一级缓存(session 级别的缓存)默认开启,不能关闭

     缓存的是id,和对象。

        Session session=demo.openSession();
        
        //直接对数据库发出语句进行查询,并生成对象
        List<User> user1s=
        session.createQuery("from User",User.class).setFirstResult(0).setMaxResults(5).list();
        //直接对数据库发出语句进行查询,拿id去缓存中查找到了对象,就不生成对象
        List<User> user2s=
        session.createQuery("from User",User.class).setFirstResult(0).setMaxResults(5).list();

        System.out.println(user1s.get(0)==user2s.get(0));
        //获取缓存中的数据
        User user =session.load(User.class, 2l);
        System.out.println(user.getName());
        
        session.close();

输出结果:

[11:15:02.888] [DEBUG] []   SQL:  
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
[11:15:02.912] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [2]
[11:15:02.925] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer0]
[11:15:02.929] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [5]
[11:15:02.930] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer1]
[11:15:02.931] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [8]
[11:15:02.932] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer2]
[11:15:02.934] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [11]
[11:15:02.935] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer3]
[11:15:02.940] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [14]
[11:15:02.940] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer4]
[11:15:02.969] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[11:15:02.970] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#2]
[11:15:03.067] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#5]
[11:15:03.070] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#5]
[11:15:03.071] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#8]
[11:15:03.072] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#8]
[11:15:03.073] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#11]
[11:15:03.074] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#11]
[11:15:03.075] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#14]
[11:15:03.076] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#14]
[11:15:04.779] [DEBUG] []   SQL:  
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
[11:15:04.783] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [2]
[11:15:04.784] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [5]
[11:15:04.785] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [8]
[11:15:04.786] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [11]
[11:15:04.786] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [14]
true
Brett Meyer0
View Code

  1.2 二级缓存(sessionFactory缓存)手动开启

     开启方法: 在 hibernate.properties里配置(如果与spring结合,请搜索spring里对应的配置)   在annotation中,我们还需要在这个类上加上这样一个注解:@Cache

hibernate.cache.use_second_level_cache true
hibernate.cache.region.factory_class org.hibernate.cache.SingletonEhCacheRegionFactory

     缓存的是id,和对象。(执行sql时,查出来所有的对象,按id和对象缓存。

        //直接对数据库发出语句进行查询,并生成对象
        List<User> user1s=
        session.createQuery("from User",User.class).setFirstResult(0).setMaxResults(5).list();
        session.close();
        session=demo.openSession();
        //使用二级缓存
        User user =session.load(User.class, 2l);
        System.out.println(user.getName());
        session.close();

输出结果:

[15:11:47.912] [DEBUG] []   SQL:  
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
[15:11:47.930] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [2]
[15:11:47.938] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer0]
[15:11:47.940] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [5]
[15:11:47.941] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer1]
[15:11:47.941] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [8]
[15:11:47.941] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer2]
[15:11:47.941] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [11]
[15:11:47.941] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer3]
[15:11:47.942] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [14]
[15:11:47.942] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer4]
[15:11:47.959] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[15:11:47.960] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#2]
[15:11:47.971] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#5]
[15:11:47.972] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#5]
[15:11:47.972] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#8]
[15:11:47.972] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#8]
[15:11:47.973] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#11]
[15:11:47.973] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#11]
[15:11:47.974] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#14]
[15:11:47.974] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#14]
[15:11:48.006] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[15:11:48.006
View Code

  1.3 查询缓存(sessionFactory缓存)手动开启

       开启方法:hibernate.properties    

      hibernate.cache.use_query_cache true 代码中要显示得使用 .setCacheable(true)     在annotation中,我们还需要在这个类上加上这样一个注解:@Cacheable

     缓存的sql语句和对象id (所以要使用查询缓存时,二级缓存必须开启

        Session session = demo.openSession();

        // 直接对数据库发出语句进行查询,并生成对象
        List<User> user1s = session.createQuery("from User", User.class).setCacheable(true).setFirstResult(0).setMaxResults(5).list();
        session.close();
        session = demo.openSession();
        // 使用二级缓存
        User user = session.load(User.class, 2l);
        System.out.println(user.getName());
        session.close();

        session = demo.openSession();
        // 使用查询缓存
        List<User> user2s = session.createQuery("from User", User.class).setCacheable(true).setFirstResult(0)
                .setMaxResults(5).list();
        System.out.println(user1s.get(0) == user2s.get(0));
        session.close();

输出结果:

[15:14:58.165] [DEBUG] []   SQL:  
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.name as name2_2_ 
    from
        User user0_ limit ?
[15:14:58.177] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [2]
[15:14:58.183] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer0]
[15:14:58.184] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [5]
[15:14:58.184] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer1]
[15:14:58.184] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [8]
[15:14:58.185] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer2]
[15:14:58.185] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [11]
[15:14:58.185] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer3]
[15:14:58.185] [TRACE] []   BasicExtractor:  extracted value ([id1_2_] : [BIGINT]) - [14]
[15:14:58.185] [TRACE] []   BasicExtractor:  extracted value ([name2_2_] : [VARCHAR]) - [Brett Meyer4]
[15:14:58.198] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[15:14:58.199] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#2]
[15:14:58.208] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#5]
[15:14:58.208] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#5]
[15:14:58.209] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#8]
[15:14:58.209] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#8]
[15:14:58.210] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#11]
[15:14:58.210] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#11]
[15:14:58.211] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#14]
[15:14:58.211] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#14]
[15:14:58.246] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[15:14:58.246] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#2]
Brett Meyer0
[15:14:58.248] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#2]
[15:14:58.248] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#2]
[15:14:58.249] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#5]
[15:14:58.249] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#5]
[15:14:58.250] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#8]
[15:14:58.250] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#8]
[15:14:58.250] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#11]
[15:14:58.250] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#11]
[15:14:58.251] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.projects#14]
[15:14:58.251] [TRACE] []   CollectionType:  Created collection wrapper: [com.zhou.test.hibernate.cache.entity.User.skills#14]
false
View Code

  1.4 hibernate的N+1问题。

    一般而言说n+1意思是,无论在一对多还是多对一当查询出n条数据之后,每条数据会关联的查询1次他的关联对象,这就叫做n+1

    对需要N+1的地方(不直接查询出对象)解决方法:

    1.延迟加载,当需要的时候才查询,不需要就不查询,但是感觉这种方式治标不治本,尤其是在那种报表统计查询的时候更为明显。

    2.fetch="join",默认是fetch="select",这个其实说白了就是一个做外连接,允许外键为空的情况之下。

    不需要N+1的地方则相反。