首页 技术 正文
技术 2022年11月15日
0 收藏 992 点赞 3,695 浏览 12009 个字

https://blog.csdn.net/u012411414/article/details/50483185

有一下几点需要理清才行:

一级缓存是session缓存 session关闭就小时

二级缓存是sessionFactory级别的缓存 一个应用程序只有一个 多个线程共享  不要把经常修改的对象放到二级缓存中 二级缓存中放一些查询的对象

1 首先是在hibernate,cfg.xml文件中进行配置:

添加下列配置项

  1.  <property name=”hibernate.cache.use_second_level_cache”>true</property>
  2.  <!– 使用哪种缓存提供的类 哪种缓存 –>
  3.  <property name=”hibernate.cache.provider_class”>org.hibernate.cache.EhCacheProvider</property>
  4.  <!– 使用查询缓存–>
  5.  <property name=”hibernate.cache.use_query_cache”>true</property>
  6.  <!– ehcache.xml的配置文件路径 –>
  7.  <property name=”hibernate.cache.provider_configuration_file_resource_path”>ehcache.xml</property>

在需要使用二级缓存的对象配置文件上:

  1.  <class name=”Student” table=”t_stu”>
  2.  <!– <cache usage=”read-only” /> –>
  3.  <id name=”id”>
  4.  <generator class=”native”></generator>
  5.  </id>
  6.  <!– 注意:version 一定要加在ID后面 property前面 –>
  7.  <version name=”version” />
  8.  <property name=”name” />
  9.  <property name=”sex” />
  10.  <many-to-one name=”classroom” column=”cid” fetch=”join” />
  11.  </class>

ehcache.xml中的配置:

  1.  <defaultCache
  2.  maxElementsInMemory=”10000″
  3.  eternal=”false”
  4.  timeToIdleSeconds=”120″
  5.  timeToLiveSeconds=”120″
  6.  overflowToDisk=”true”
  7.  />
  1.  <!– 每一个独立的cache可以单独为不同的对象进行设置 如果找不到就用默认的cache–>
  2.   <cache name=”com.itany.model.Student”
  3.   maxElementsInMemory=”10000″
  4.   eternal=”false”
  5.   timeToIdleSeconds=”300″
  6.   timeToLiveSeconds=”600″
  7.   overflowToDisk=”true”
  8.   />

2 N+1问题

如果使用iterator返回列表 对于hibernate而言 
         它仅仅是查询了id列表的SQL 在进行iterator迭代的时候 
         再会根据id一个个去数据库查询具体对象 因此发出多条SQL 这就是典型的N+1问题 避免它
         就是不使用iterator iterator存在的原因 
         使用的地方:
         因为有可能需要查询2次 第一次list全部查询出来 存在二级缓存中 第二次 用Iterator数据库查id,再根据ID从二级缓存的对象中查询更快

  1.   session = HibernateUtil.openSession();
  2.   Iterator<Student> it = session.createQuery(“from Student”).setFirstResult(0).setMaxResults(12).iterate();
  3.   while (it.hasNext())
  4.   {
  5.   Student stu = it.next();
  6.   System.out.println(stu.getName());
  7.   }

3  重要:二级缓存缓存的是对象  查询缓存缓存的是ID 这是两种不同的缓存  谁也不依赖谁   查询缓存也是sessionFactory级别的缓存

查询缓存是针对HQL语句的缓存  查询缓只缓存ID 而不会缓存对象
     1 但是使用查询缓存最好打开二级缓存 因为在查询缓存中查到ID后可以直接去
     二级缓存中查找 不然的话又是N+1问题 多次根据查询缓存中的ID去数据库查询
     2 若打开了二级缓存 但是没有打开查询缓存(HQL不一致、参数不一致、查询缓存没开、
     setCacheable(true)没写等原因)那么还是会直接从数据库中查询一次、
     因为需要借助查询缓存查ID再到二级缓存中查对象
     3 注意:load方式可以直接从二级缓存中查对象 不必借助查询缓存
     4如果取得只是某些属性(而不是完整对象) 那么不会进行二级缓存见test04
     5 查询缓存 工作顺序:如果正常开启了查询缓存(HQL完全一致 且set(True)),先去查询缓存中查ID
          再根据查询到的ID去二级缓存中查对象 若此时二级缓存打开了 那么不会发SQL
         若二级缓存没打开  那么此时会再次根据查到的ID去数据库中查询

4 代码中使用查询缓存

  1.   List<Object[]> ls = session.createQuery(“select stu from Student stu where name like ?”)
  2.   .setCacheable(true).setParameter(0, “%张%”).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存

5 此时关闭了二级缓存(存对象)
    打开了查询缓存(存ID) 第二个人查询缓存只查到ID 会根据ID 去二级缓存查对象  但是没有  所以去数据库查  发出大量SQL

6 查询缓存很少使用 因为很少HQL完全一样
          因为只要HQL语句不一样 就不会开启查询缓存 
          只有两个完全一样的 并且参数都一样的 才能使用查询缓存

    1.  public class TestSecondCache
    2.  {
    3.   /*
    4.   * 重要:二级缓存缓存的是对象  查询缓存缓存的是ID 这是两种不同的缓存
    5.   * 谁也不依赖谁  
    6.   * 1 但是使用查询缓存最好打开二级缓存 因为在查询缓存中查到ID后可以直接去
    7.   * 二级缓存中查找 不然的话又是N+1问题 多次根据查询缓存中的ID去数据库查询
    8.   * 2 若打开了二级缓存 但是没有打开查询缓存(HQL不一致、参数不一致、查询缓存没开、
    9.   * setCacheable(true)没写等原因)那么还是会直接从数据库中查询一次、
    10.   * 因为需要借助查询缓存查ID再到二级缓存中查对象
    11.   * 3 注意:load方式可以直接从二级缓存中查对象 不必借助查询缓存
    12.   *
    13.   * 如果取得只是某些属性(而不是完整对象) 那么不会进行二级缓存见test04
    14.   */
    15.   
    16.   @Test
    17.   public void test01()
    18.   {
    19.   /*
    20.   * 不可以缓存 Ehcache是看SQL是否一样
    21.   */
    22.   Session session = null;
    23.   try
    24.   {
    25.   session = HibernateUtil.openSession();
    26.   Student s=(Student)session.load(Student.class,1);
    27.   System.out.println(s.getName());
    28.   }
    29.   catch (HibernateException e)
    30.   {
    31.   e.printStackTrace();
    32.   }
    33.   finally
    34.   {
    35.   if (null != session)
    36.   HibernateUtil.closeSession(session);
    37.   }
    38.   Session session2 = null;
    39.   /*
    40.   * 此时session已经关闭 但再次查询 仍然可以不发SQL 二级缓存起作用了
    41.   */
    42.   try
    43.   {
    44.   session2 = HibernateUtil.openSession();
    45.   Student s2=(Student)session2.load(Student.class,1);//这种写法 根据ID去二级缓存中查询
    46.   System.out.println(s2.getName());
    47.   }
    48.   catch (HibernateException e)
    49.   {
    50.   e.printStackTrace();
    51.   }
    52.   finally
    53.   {
    54.   if (null != session2)
    55.   HibernateUtil.closeSession(session2);
    56.   }
    57.   }
    58.   @Test
    59.   public void test02()
    60.   {
    61.   /*
    62.   *
    63.   */
    64.   Session session = null;
    65.   try
    66.   {
    67.   session = HibernateUtil.openSession();
    68.   Student s=(Student)session.load(Student.class,1);
    69.   System.out.println(s.getName());
    70.   }
    71.   catch (HibernateException e)
    72.   {
    73.   e.printStackTrace();
    74.   }
    75.   finally
    76.   {
    77.   if (null != session)
    78.   HibernateUtil.closeSession(session);
    79.   }
    80.   Session session2 = null;
    81.   Transaction trans=null;
    82.   /*
    83.   * 会报错 因为二级缓存 在Student上设置的是 read-only 因此不能写入
    84.   * 最好不要设置 read write因为hibernate要频繁的加锁 解锁 影响效率 还不如不用二级缓存
    85.   */
    86.   try
    87.   {
    88.   session2 = HibernateUtil.openSession();
    89.   trans=session2.beginTransaction();
    90.   Student s2=(Student)session2.load(Student.class,1);
    91.   s2.setName(“zhangasnsss”);
    92.   System.out.println(s2.getName());
    93.   trans.commit();
    94.   }
    95.   catch (HibernateException e)
    96.   {
    97.   e.printStackTrace();
    98.   }
    99.   finally
    100.   {
    101.   if (null != session2)
    102.   HibernateUtil.closeSession(session2);
    103.   }
    104.   }
    105.   @Test
    106.   public void test03()
    107.   {
    108.   /*
    109.   *
    110.   */
    111.   Session session = null;
    112.   Transaction trans = null;
    113.   try
    114.   {
    115.   session = HibernateUtil.openSession();
    116.   List<Student> ls = session.createQuery(“from Student”).list();
    117.   Iterator<Student> it = ls.iterator();
    118.   while (it.hasNext())
    119.   {
    120.   Student stu = it.next();
    121.   System.out.println(stu.getName());
    122.   }
    123.   }
    124.   catch (HibernateException e)
    125.   {
    126.   e.printStackTrace();
    127.   }
    128.   finally
    129.   {
    130.   if (null != session)
    131.   HibernateUtil.closeSession(session);
    132.   }
    133.   
    134.   try
    135.   {
    136.   session = HibernateUtil.openSession();
    137.   Student s=(Student)session.load(Student.class,1);
    138.   System.out.println(s.getName());
    139.   }
    140.   catch (HibernateException e)
    141.   {
    142.   e.printStackTrace();
    143.   }
    144.   finally
    145.   {
    146.   if (null != session)
    147.   HibernateUtil.closeSession(session);
    148.   }
    149.   }
    150.   @Test
    151.   public void test04()
    152.   {
    153.   /*
    154.   *
    155.   */
    156.   Session session = null;
    157.   Transaction trans = null;
    158.   try
    159.   {
    160.   session = HibernateUtil.openSession();
    161.   List<Object[]> ls = session.createQuery(“select stu.id,stu.name from Student stu”).list();
    162.   }
    163.   catch (HibernateException e)
    164.   {
    165.   e.printStackTrace();
    166.   }
    167.   finally
    168.   {
    169.   if (null != session)
    170.   HibernateUtil.closeSession(session);
    171.   }
    172.   /*
    173.   * 以上代码仅仅去了id和name 而二级缓存是缓存对象的 所以上一段代码不会使用二级缓存
    174.   * 此时就会发出相应的SQL
    175.   */
    176.   try
    177.   {
    178.   session = HibernateUtil.openSession();
    179.   Student s=(Student)session.load(Student.class,1);
    180.   System.out.println(s.getName());
    181.   }
    182.   catch (HibernateException e)
    183.   {
    184.   e.printStackTrace();
    185.   }
    186.   finally
    187.   {
    188.   if (null != session)
    189.   HibernateUtil.closeSession(session);
    190.   }
    191.   }
    192.   @Test
    193.   public void test05()
    194.   {
    195.   /*
    196.   * iterator 作用就是配合二级缓存使用 最好
    197.   */
    198.   Session session = null;
    199.   Transaction trans = null;
    200.   try
    201.   { //一条SQL
    202.   session = HibernateUtil.openSession();
    203.   List<Object[]> ls = session.createQuery(“select stu from Student stu”).list();
    204.   }
    205.   catch (HibernateException e)
    206.   {
    207.   e.printStackTrace();
    208.   }
    209.   finally
    210.   {
    211.   if (null != session)
    212.   HibernateUtil.closeSession(session);
    213.   }
    214.   /* 1条SQL
    215.   * 由于学生的对象经过上面查询对象之后 已经存在于二级缓存之中
    216.   * 此时正好直接使用iterator 首先会查询通过1条取ID的语句 然后再获取对象时候去二级缓存中查询
    217.   * 有的话 直接用 不会产生N+1问题
    218.   *
    219.   * 若没二级缓存 我们直接使用iterator会首先产生一条查ID的语句
    220.   * 再在获取对象的时候再去数据库中取 那么这是就会产生N+1问题
    221.   */
    222.   try
    223.   {
    224.   session = HibernateUtil.openSession();
    225.   Iterator<Student> it = session.createQuery(“from Student”).iterate();
    226.   while (it.hasNext())
    227.   {
    228.   Student stu = it.next();
    229.   System.out.println(stu.getName());
    230.   }
    231.   }
    232.   catch (HibernateException e)
    233.   {
    234.   e.printStackTrace();
    235.   }
    236.   finally
    237.   {
    238.   if (null != session)
    239.   HibernateUtil.closeSession(session);
    240.   }
    241.   }
    242.   @Test
    243.   public void test06()
    244.   {
    245.   /*
    246.   * 与上面一个几乎一样 区别在于iterator换成list()
    247.   * 虽然第一次已经二级缓存了 但是不能决定我再去不去数据库中查询
    248.   *
    249.   * 重要 :如果希望第二次不发SQL 那就要使用查询缓存
    250.   * 查询缓存是针对HQL语句的缓存 查询缓只缓存ID 而不会缓存对象
    251.   */
    252.   Session session = null;
    253.   
    254.   Transaction trans = null;
    255.   try
    256.   { //一条SQL
    257.   session = HibernateUtil.openSession();
    258.   List<Object[]> ls = session.createQuery(“select stu from Student stu”).list();
    259.   }
    260.   catch (HibernateException e)
    261.   {
    262.   e.printStackTrace();
    263.   }
    264.   finally
    265.   {
    266.   if (null != session)
    267.   HibernateUtil.closeSession(session);
    268.   }
    269.   /* 1条SQL 和上一条一模一样
    270.   *
    271.   */
    272.   try
    273.   {
    274.   session = HibernateUtil.openSession();
    275.   List<Student> ls = session.createQuery(“select stu from Student stu”).list();
    276.   Iterator<Student> it=ls.iterator();
    277.   while (it.hasNext())
    278.   {
    279.   Student stu = it.next();
    280.   System.out.println(stu.getName());
    281.   }
    282.   }
    283.   catch (HibernateException e)
    284.   {
    285.   e.printStackTrace();
    286.   }
    287.   finally
    288.   {
    289.   if (null != session)
    290.   HibernateUtil.closeSession(session);
    291.   }
    292.   }
    293.   @Test
    294.   public void test07()
    295.   {
    296.   /*
    297.   * 设置了查询缓存为true
    298.   */
    299.   Session session = null;
    300.   Transaction trans = null;
    301.   try
    302.   { //一条SQL
    303.   session = HibernateUtil.openSession();
    304.   List<Object[]> ls = session.createQuery(“select stu from Student stu”)
    305.   .setCacheable(true).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存
    306.   }
    307.   catch (HibernateException e)
    308.   {
    309.   e.printStackTrace();
    310.   }
    311.   finally
    312.   {
    313.   if (null != session)
    314.   HibernateUtil.closeSession(session);
    315.   }
    316.   /*0条SQL
    317.   *
    318.   */
    319.   try
    320.   {
    321.   session = HibernateUtil.openSession();
    322.   List<Student> ls = session.createQuery(“select stu from Student stu”)
    323.   .setCacheable(true).list();
    324.   Iterator<Student> it=ls.iterator();
    325.   while (it.hasNext())
    326.   {
    327.   Student stu = it.next();
    328.   System.out.println(stu.getName());
    329.   }
    330.   }
    331.   catch (HibernateException e)
    332.   {
    333.   e.printStackTrace();
    334.   }
    335.   finally
    336.   {
    337.   if (null != session)
    338.   HibernateUtil.closeSession(session);
    339.   }
    340.   }
    341.   @Test
    342.   public void test08()
    343.   {
    344.   /*
    345.   * 此时无法使用查询缓存 查询缓存很少使用 因为很少HQL完全一样
    346.   * 因为只要HQL语句不一样 就不会开启查询缓存
    347.   * 只有两个完全一样的 并且参数都一样的 才能使用查询缓存
    348.   */
    349.   Session session = null;
    350.   Transaction trans = null;
    351.   try
    352.   { //一条SQL
    353.   session = HibernateUtil.openSession();
    354.   List<Object[]> ls = session.createQuery(“select stu from Student stu where name like ?”)
    355.   .setCacheable(true).setParameter(0, “%张%”).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存
    356.   }
    357.   catch (HibernateException e)
    358.   {
    359.   e.printStackTrace();
    360.   }
    361.   finally
    362.   {
    363.   if (null != session)
    364.   HibernateUtil.closeSession(session);
    365.   }
    366.   /*
    367.   *
    368.   */
    369.   try
    370.   {
    371.   //一条SQL
    372.   session = HibernateUtil.openSession();
    373.   List<Student> ls = session.createQuery(“select stu from Student stu where name like ?”)
    374.   .setCacheable(true).setParameter(0, “%王%”).list();
    375.   Iterator<Student> it=ls.iterator();
    376.   while (it.hasNext())
    377.   {
    378.   Student stu = it.next();
    379.   System.out.println(stu.getName());
    380.   }
    381.   }
    382.   catch (HibernateException e)
    383.   {
    384.   e.printStackTrace();
    385.   }
    386.   finally
    387.   {
    388.   if (null != session)
    389.   HibernateUtil.closeSession(session);
    390.   }
    391.   }
    392.   @Test
    393.   public void test09()
    394.   {
    395.   /*
    396.   * 此时关闭了二级缓存(存对象)
    397.   * 打开了查询缓存(存ID)
    398.   * !!!工作顺序:如果正常开启了查询缓存(HQL完全一致 且set(True)),先去查询缓存中查ID
    399.   * 再根据查询到的ID去二级缓存中查对象 若此时二级缓存打开了 那么不会发SQL
    400.   * 若二级缓存没打开 那么此时会再次根据查到的ID去数据库中查询
    401.   */
    402.   Session session = null;
    403.   Transaction trans = null;
    404.   try
    405.   { //一条SQL
    406.   session = HibernateUtil.openSession();
    407.   List<Object[]> ls = session.createQuery(“select stu from Student stu where name like ?”)
    408.   .setCacheable(true).setParameter(0, “%张%”).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存
    409.   }
    410.   catch (HibernateException e)
    411.   {
    412.   e.printStackTrace();
    413.   }
    414.   finally
    415.   {
    416.   if (null != session)
    417.   HibernateUtil.closeSession(session);
    418.   }
    419.   /*
    420.   *
    421.   */
    422.   try
    423.   {
    424.   //此时关闭了student的二级缓存 打开了查询缓存 发出大量SQL
    425.   session = HibernateUtil.openSession();
    426.   List<Student> ls = session.createQuery(“select stu from Student stu where name like ?”)
    427.   .setCacheable(true).setParameter(0, “%张%”).list();
    428.   Iterator<Student> it=ls.iterator();
    429.   while (it.hasNext())
    430.   {
    431.   Student stu = it.next();
    432.   System.out.println(stu.getName());
    433.   }
    434.   }
    435.   catch (HibernateException e)
    436.   {
    437.   e.printStackTrace();
    438.   }
    439.   finally
    440.   {
    441.   if (null != session)
    442.   HibernateUtil.closeSession(session);
    443.   }
    444.   }
    445.   @Test
    446.   public void test10()
    447.   {
    448.   /*
    449.   * 此时打开了二级缓存(存对象)
    450.   * 打开了查询缓存(存ID)
    451.   * !!!!工作顺序:如果正常开启了查询缓存,先去查询缓存中查ID
    452.   * 再根据查询到的ID去二级缓存中查对象 若此时二级缓存打开了 那么不会发SQL
    453.   * 若二级缓存没打开 那么此时会再次根据查到的ID去数据库中查询
    454.   */
    455.   Session session = null;
    456.   Transaction trans = null;
    457.   try
    458.   { //一条SQL
    459.   session = HibernateUtil.openSession();
    460.   List<Object[]> ls = session.createQuery(“select stu from Student stu where name like ?”)
    461.   .setCacheable(true).setParameter(0, “%张%”).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存
    462.   }
    463.   catch (HibernateException e)
    464.   {
    465.   e.printStackTrace();
    466.   }
    467.   finally
    468.   {
    469.   if (null != session)
    470.   HibernateUtil.closeSession(session);
    471.   }
    472.   /*
    473.   *
    474.   */
    475.   try
    476.   {
    477.   //此时打开了student的二级缓存 打开了查询缓存 不发SQL
    478.   session = HibernateUtil.openSession();
    479.   List<Student> ls = session.createQuery(“select stu from Student stu where name like ?”)
    480.   .setCacheable(true).setParameter(0, “%张%”).list();
    481.   Iterator<Student> it=ls.iterator();
    482.   while (it.hasNext())
    483.   {
    484.   Student stu = it.next();
    485.   System.out.println(stu.getName());
    486.   }
    487.   }
    488.   catch (HibernateException e)
    489.   {
    490.   e.printStackTrace();
    491.   }
    492.   finally
    493.   {
    494.   if (null != session)
    495.   HibernateUtil.closeSession(session);
    496.   }
    497.   }
    498.   @Test
    499.   public void test11()
    500.   {
    501.   /*
    502.   * 此时打开了二级缓存(存对象)
    503.   * 打开了查询缓存(存ID)
    504.   * !!!!工作顺序:如果正常开启了查询缓存,先去查询缓存中查ID
    505.   * 再根据查询到的ID去二级缓存中查对象 若此时二级缓存打开了 那么不会发SQL
    506.   * 若二级缓存没打开 那么此时会再次根据查到的ID去数据库中查询
    507.   */
    508.   Session session = null;
    509.   Transaction trans = null;
    510.   try
    511.   { //一条SQL
    512.   session = HibernateUtil.openSession();
    513.   List<Object[]> ls = session.createQuery(“select stu from Student stu where name like ?”)
    514.   .setCacheable(true).setParameter(0, “%张%”).list();//开启查询缓存 查询缓存也是sessionFactory级别的缓存
    515.   }
    516.   catch (HibernateException e)
    517.   {
    518.   e.printStackTrace();
    519.   }
    520.   finally
    521.   {
    522.   if (null != session)
    523.   HibernateUtil.closeSession(session);
    524.   }
    525.   /*
    526.   *
    527.   */
    528.   try
    529.   {
    530.   //此时虽然打开了student的二级缓存 但是不能使用查询缓存(HQL不一致)导致没法通过查询缓存查ID去
    531.   //二级缓存中查对象
    532.   //所以仍然发出一条SQL 从数据库中查询
    533.   session = HibernateUtil.openSession();
    534.   List<Student> ls = session.createQuery(“select stu from Student stu where name like ?”)
    535.   .setCacheable(true).setParameter(0, “%张三%”).list();
    536.   Iterator<Student> it=ls.iterator();
    537.   while (it.hasNext())
    538.   {
    539.   Student stu = it.next();
    540.   System.out.println(stu.getName());
    541.   }
    542.   }
    543.   catch (HibernateException e)
    544.   {
    545.   e.printStackTrace();
    546.   }
    547.   finally
    548.   {
    549.   if (null != session)
    550.   HibernateUtil.closeSession(session);
    551.   }
    552.   }
    553.  }
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,000
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,512
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,358
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,141
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,771
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,849