我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > session.flush()与session.clear()有什么区别
总共48087条微博

动态微博

查看: 871|回复: 0

session.flush()与session.clear()有什么区别

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2015-05-19 15:37:33 |只看该作者 |倒序浏览
    Session Clear()与 Flush() 解释
    6 G# w- l- c: W& N& P- y* H! a1.Clear 方法; G3 j# W# a% a+ l1 J
      无论是Load 还是 Get 都会首先查找缓存(一级缓存) 如果没有,才会去数据库查找,调用Clear() 方法,可以强制清除Session缓存。! c' r) X+ [9 h  C
    例:# w1 F& {6 `! ^5 p- f. A& Q
    1. public void testClear(){
      8 }. X- S9 \) t; m& `
    2.                 Session session =  hibernateUitl.getSessionFactory().getCurrentSession();
      / o9 ^# I/ a2 e- u  A+ `- M/ l
    3.                 session.beginTransaction();  u, c. k" N* M* V; H9 u
    4.                 Teacher t = (Teacher) session.get(Teacher.class, 3);
      , z3 r, i- j- s( W. ^( Y
    5.                 System.out.println(t.getName());1 n8 S3 j8 J' f$ G( |" S/ x! u5 |! s
    6.                 Teacher t2 = (Teacher) session.get(Teacher.class, 3);
      ( w, J& M' x$ q& H+ v9 U
    7.                 System.out.println(t2.getName());
      0 i) d4 c5 d) E7 _( S
    8.                 session.getTransaction().commit();
      + S; g& e. ?9 E
    9.         }! ^0 ]4 s8 U" j7 `, a
    复制代码
    这里虽然用了2个get方法(get方法会立即执行sql语句),但因为第一次执行了会缓存一个ID为3的实体,所以虽然有2个get方法只执行一次SQL语句。
    0 W+ K$ b0 k$ P
    1. public void testClear(){- X1 y/ W; O  p. v" }, y
    2.                 Session session =  HibernateUitl.getSessionFactory().getCurrentSession();* `5 j' _6 N+ ?! s8 x9 G, [
    3.                 session.beginTransaction();. _7 z) F& M9 j
    4.                 Teacher t = (Teacher) session.get(Teacher.class, 3);
      ! s( w/ M5 O6 V  |7 B
    5.                 System.out.println(t.getName());. W0 B- U+ n4 t
    6.                 session.clear();//这里不clear只会执行一次sql语句,有clear会执行2次
      3 M1 `: E" A0 V
    7.                 Teacher t2 = (Teacher) session.get(Teacher.class, 3);( [- e& x# b/ v8 P& c) w/ Z6 x
    8.                 System.out.println(t2.getName());
      7 G0 H' l8 G6 e! ]% ~
    9.                 session.getTransaction().commit();4 I6 C! ^- P$ A4 _: r2 P! H/ H
    10.         }
      $ u+ h; J2 A  h0 G5 t
    复制代码

    5 O, P1 |0 j' a1 N这里在第2次get前执行session.clear(),我们把hibernate show_sql 出来,它就会执行2次sql语句了。
    . l/ O2 `5 O% \所以session.clear()会清除缓存。2 z( s0 b. Z" A0 }( {# p' }
    2.Flush方法: f0 U* U1 }: ?: t
      可以强制进行从内存到数据库的同步。5 J9 ?* V# u3 }& l9 |& K0 L* R' Y
    例:
    / b) y0 ]- f' q& k3 w
    1. @Test
      ' B0 L+ g5 s* o+ e* H
    2.         /**
      % B: D( {! h' P
    3.          * flush 强制与数据库同步
      - y  v: B* }9 ?
    4.          */! A0 U3 t5 O- W6 P% e+ j
    5.         public void testFlush(){
      8 `' n) [+ c6 E0 x. x$ {2 c: F
    6.                 Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
      $ q$ q  i/ O( P. O+ n
    7.                 session.beginTransaction();
      1 X1 \2 A: L: Z1 I1 C1 F
    8.                 Teacher t = (Teacher) session.get(Teacher.class, 3);; ~+ T$ Z3 d7 d( b7 @2 I
    9.                 t.setName("yyy");
      7 W# l$ L! b! s3 A! r5 q
    10. 1 C2 D, W4 m/ ~1 T3 y8 g: n9 r
    11.                 t.setName("yyyyy");
      # h' ^' }0 G+ S. ]& q6 c! T  Z% H; j
    12.                 session.getTransaction().commit();
      % }* E& u" g" f& `6 P# k# X% G
    13.         }  t5 F1 E! |+ I7 v2 r8 l

    14. * h" H$ h. ~  J; |0 \  E% f+ N
    15. 6 f% q% f3 G/ Y9 z
    复制代码
    看这段代码,我们setName() 2次, 但程序只会更改数据库一次,在commit时。4 A; y7 Y. [: Z( g. J
    1. @Test6 W( a0 M. H$ m% Y
    2.         /**5 v) N- t* f1 `4 u. O1 w! n
    3.          * flush 强制与数据库同步
      . n8 B- U; A4 l; t8 v
    4.          */7 w* ^' Z$ L  Y% q4 |
    5.         public void testFlush(){
      $ t* C! W& x( s+ C- c0 S2 [
    6.                 Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
      , R" ?. v# K/ U1 R
    7.                 session.beginTransaction();8 |( q& E) C# j: y3 i' Y- e& b. F
    8.                 Teacher t = (Teacher) session.get(Teacher.class, 3);
      , y5 X2 o, l3 p9 u7 H! c
    9.                 t.setName("yyy");
      1 E$ E$ H# H) }& T
    10.                 session.flush();//有flush会执行2次UPDAE,没有会只执行一次3 ~' P8 m; M4 D1 _
    11.                 t.setName("yyyyy");6 w1 K7 H; |3 i: H4 L9 |- }* @
    12.                 session.getTransaction().commit();
      5 l# \* r6 F( j2 P0 ^! e  A7 ^# i
    13.         }
      9 p% x: U) w3 E' w) |; F
    14. # ^6 G6 Y1 T1 ]% j
    15. 1 W8 {4 y# U( Z' W( Y9 d
    复制代码

    % p: h0 U5 A( G+ g& U  u; A3 ~& q: M% m5 r1 w
    我们在第2次setName()时 执行session.flush().
    - R* b2 {& j2 O6 Z( c; `再看hibernate 执行的sql 语句
    ) q, ^+ d5 M( A. z9 I; l
    1. Hibernate: ! ]% S# u: ]; b+ [- F  y3 C
    2.     update, Q2 O( X* k7 o; o7 \
    3.         Teacher % ]# v' Y- _1 g/ I3 u. w
    4.     set' \1 y( J6 o/ d1 k! q2 B
    5.         birthday=?,
      ; U2 N: A* h' t
    6.         name=?,# f$ H9 V! |- }1 Y3 i+ L
    7.         title=? 6 V" h7 ]- G# b1 \& o
    8.     where
      0 A( K1 r, w" g3 x
    9.         id=?
      - `( ]0 H, ^6 b
    10. Hibernate:
      5 z5 ^2 j. t- C! r4 ~
    11.     update
      & m# E. H2 |! x, k
    12.         Teacher $ \' R9 [" u# H/ t7 f- }! S, \
    13.     set! c7 }0 o" y+ V. N  w% \
    14.         birthday=?,1 Y" `7 z* _+ C- b& a. q* p
    15.         name=?,
      9 d, u5 K; k3 f6 q& z5 E
    16.         title=?
        T; g- h& `4 w- E2 x6 i
    17.     where8 R9 k* d% |2 }- B
    18.         id=?* F) p4 J" ^, g7 `! u1 O

    19.   j% e* Y7 m2 f( j9 T$ D' i

    20. 1 y; [) ~9 r3 X8 o/ x! n: B
    复制代码

      y6 L) D% ^. E& n6 f
    5 V0 q% T: b' n0 G9 C3 ~7 U执行了2次Update
    ) X# f" b4 o, |# m& J) x* Z
    - N- F) p" k" O' Q! W( ~所以看出来flush方法会强制与数据库同步。
    ( |9 P$ h% O% `% }6 {
    " ?% Z$ Y) x( O7 B0 l, \) I. P6 C% P7 S  U8 \( ]/ Z1 o- q
    Flush方法是可以设置的,也就是fulsh什么时候执行是可以设置的* B/ c3 s2 K6 D3 R6 u) w2 H
    " a# K; V1 q' h* c2 r3 S' r2 }. s& K$ ^+ {
    在session.beginTransaction前设置FlushMode
    , P8 }0 P$ H* E$ [9 t8 J2 X. w  M/ W+ L# d: T  u. l2 D2 j# Z
    session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)' C2 `) N3 X: Q

    . D8 k2 Q* ^1 ]8 GFlushMode有5个值可选% I2 {0 d! H. L. ]" j" l. T1 B7 l

    $ `+ c  {8 |7 T2 ]$ \1 tAlways:任何代码都会Flush
      E9 N: t" C( u! X, \9 W5 bAUTO:默认方式–自动& U; c% U5 i+ G; b9 ^% T: [
    Commit:COMMIT时4 V5 e% l9 u# C7 a/ r+ O" d
    Never:始终不
    : z; @9 n, j* R. E- q" k, R2 JMANUAL:手动方式
    7 T5 p' Y: v4 D. f+ r
    1 M* c# [( X5 X  E; F设置FlushMode 有个好处是可以节省开销,比如默认session只做查询时,就可以不让他与数据库同步了。  @  ~: W" X# J
    ================================================================+ f9 c- I% @  m: N
    我说一下一些需要注意的信息:% k8 J& v3 v- K+ e" B- `/ X4 j
    / s- h4 R/ H- b  j& l
    1 session.clear()的作用是只清除session中的缓存数据,但不管缓存与数据库的同步。
    4 z, A- ?/ b8 Z+ y8 F4 e
    2 J; `2 B& s! ?4 p比如,你执行了
    % R8 [! n  ^- Y+ u8 d$ t, K7 [3 K. k' u
    Po po = new Po();
      {8 |% W# f! C; esession.save(po)," V% V- h1 k' z; e5 r# x8 S
    # h6 M' E& \2 e7 ^( z
    之后马上执行session.clear(),在事务结束的时候,这条数据是不会被持久化到数据库中的,因为一般缓存是在事务提交的时候进行清理的,当在清理缓存前就把缓存给清除了,自然就不会同步到数据库了。不过这个也有例外的情况,就是当对象使用native生成器来生成主键id时,当执行session.save()方法时,就会立马往数据库插入一条数据,这时候执行session.clear()也不会影响了。
    . l) C; U# m# Y. H: ^2 t8 M+ M: T
    ' `9 M* z+ p4 l+ Z( v2 当更新或者保存大批量数据的时候,可以每固定数量的时候,进行清理缓存,同时清除缓存:
    . ], \# w+ k4 ]( x2 @6 k- H1 X& |8 h8 h6 E1 v' i' y
    for (int i = 0; i < 1000;i ++){9 Q" T3 t+ o& Y. v

    : S: `' p0 X: _if (i /20 == 0) {
    5 y: e+ S$ r8 N) U3 I- x0 J) \% o" {
      session.flush();
    ( [% P% g" J1 P  W# z; @" N. w" V* ]% W) `8 N+ L
      session.clear();
      y* J& B; u' H7 S2 |3 D/ K. ?}
    - u- J1 q  h0 l9 I$ }' S0 H}
    2 C+ ^- Q4 I7 e: {3 n7 d6 d2 \) `1 ~9 n1 }2 \$ S
    因为把大量的对象放到session缓存中会浪费大量的内容空间。6 b# _$ G4 ^3 j, D! b/ Y

    " y5 ]8 K0 z3 V8 x2 L# D1 Z  G7 C/ `# _2 L8 z
    3 执行完session.flush()时,并不意味着数据就肯定持久化到数据库中的,因为事务控制着数据库,如果事务提交失败了,缓存中的数据还是照样会被回滚的。
    9 O: w0 C0 s2 G" q
    ; Z5 F3 D# R* V, _; b! Y4 ]3 c" ]3 B) J- ~6 f0 Y; ]. T  i/ r

    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表