TA的每日心情 | 衰 2021-2-2 11:21 |
---|
签到天数: 36 天 [LV.5]常住居民I
|
沙发
发表于 2014-09-03 21:20:54
|只看该作者
2、 定义自动代理事务管理器 , t2 o- S7 Q3 O( |. z, {& l6 r9 a
* G8 [4 Y- }/ K; J1 ]" Z0 V/ \<!-- 定义BeanNameAutoProxyCreator-->
* e' A. o& r+ K0 q- x( ~ y J. Z4 o( W* h5 D/ {+ y6 f9 J
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> , f" R5 z4 A$ U3 S4 |( l" Z
5 l# i. G# \1 f0 e5 x% \1 \# X
<!-- 如果服务层对象是接口实现类,则需要设置proxyTargetClass属性为true --> + W7 k( d, d% Y6 p ]8 A% j
4 n& }4 i* G6 w, M" _1 [
<!--<property name="proxyTargetClass" value="true"--> 3 r. k; J0 A* q+ S7 d, z5 N1 F: f
) [1 W) \" s& a& w* r3 f9 P <!-- 指定对满足哪些bean name的bean自动生成业务代理 -->
% ?& D1 \' `9 i: u$ _. b* Z2 R( K' H+ I/ G8 K) U% U2 X
<property name="beanNames"> 9 z7 T3 h% J& ^/ T7 \5 ?: [
& G- v; P! @5 i- R <!-- 下面是所有需要自动创建事务代理的bean--> 1 H! [; |3 q! L# |
& r: r+ ?) j+ h9 s
<list> 2 C4 E, D, L- W6 |, ~( R
' H; w% Z! z3 ?7 t
<value>us</value>
1 z! }- y$ c: A5 G v) k0 C$ E; S( }' [- a) d: f: z' M
</list>
' L/ |/ _, Y: R6 C
2 W1 |& F! ~" A+ J2 l <!-- 此处可增加其他需要自动创建事务代理的bean-->
9 ~# Z+ o- o& F( A. a
0 x& _2 }" l# x8 M3 _5 J </property>
0 @6 B+ q2 V1 [7 ~ a9 b8 c
8 ]+ m6 p6 \5 z/ p' d <!-- 下面定义BeanNameAutoProxyCreator所需的事务拦截器-->
0 @; W( J# z( ^9 P# q- m; j
6 D$ s8 o# u: d' `- D <property name="interceptorNames"> ; U* E( V; o [( q! @! c- K
9 I7 D w* m% i. B% X. N <list> . v- R3 @4 ~" |$ y3 \- K
/ ~5 y/ z5 F( K, j# Q
<!-- 此处可增加其他新的Interceptor -->
; w- \. ]3 J7 v. G- m* W5 K
1 a( W' L" M6 A4 R8 d <value>transactionInterceptor</value>
5 z% m/ p, x4 r
. L4 ~! M! \" k3 h& z </list>
' @% b I% G/ Z1 R
$ C5 D, T/ t; R8 {8 b8 G- P; @( W </property>
( I& A# \; A: j; m& `
1 y2 R0 \' S! [</bean> # d. p$ Y! [7 F" {& ^1 W) L
_! R( U/ R- @" c6 }! L
然后我们在程序中调用时应如下:
& m: I/ E: [' K: |" F! c, u6 u% u! L5 F. ?! u# e3 Q
UserService us = (UserService) app.getBean("us");
6 t' E( z5 B2 Q
& K! d; V% q# D, w2 {7 A注:注意与上面使用TransactionProxyFactoryBean时的调用区别,此处我们用getbean时直接取原服务层对象的id,不需要去配置目标bea,这也正是 ) c# r. i2 B! T. A
( x9 E6 z4 }7 a$ A
BeanNameAutoProxyCreator(根据bean名称自动代理)的含义所在 9 c+ n) A# f) j, {% }2 }
% P/ G+ Z D' n6 a9 d4 A+ m2 Z( F7 U* t3 ~7 N6 \" v
! t; ^- d, V9 u( V) Y) F8 k
附录:
7 ?$ B. g5 }9 @# \3 e& ?; }7 p7 |9 G! C+ ^4 U" k
1、关于hibernate的属性详解: & Y# n0 E! a: m7 i/ m
% C, s# H4 _8 k0 C1 D" O
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
# D& d( Q0 u( Q N: A6 P& ], Z1 \7 X0 ]
<!-- 以下配置都是使用 jdbc.properties 属性文件中的配置,而之所以可以这样写,就是因为有 属性占位符配置的原因 --> : P1 k0 _0 \ D
$ l4 ~# p8 }7 q" d( h3 A
<property name="driverClass" value="${jdbc.driverClassName}"/>
- B [( j7 l6 N. d
( G8 ^' A- W- H<property name="jdbcUrl" value="${jdbc.url}"/>
5 P: ?. u9 w( ^: D
3 Q( U- y5 y: H/ m<property name="user" value="${jdbc.username}"/> - @, _( e3 J- Q- k+ E& }3 D- s5 i
6 u7 C; q( J7 g5 c1 w+ ]0 t/ }2 I
<property name="password" value="${jdbc.password}"/> % m! v. K* Q: i+ V h; n
0 {1 W- U1 V# [4 R# P6 U<!-- 连接池维持的最小的连接个数 -->
, y1 \' |& u& g! N0 x& q( |
8 r: u% }, G" d0 Q& H5 m! R, R<property name="minPoolSize" value="5"/> 6 _! o" S& L" x2 |1 {. X5 N
@# q2 S' u3 w: w# R8 J7 B9 z
<!-- 连接池维持的最大的连接个数 --> $ ?1 O9 p( h- ?4 x. q
8 F' |, f# i1 A7 J5 M1 j1 V; {<property name="maxPoolSize" value="20"/> % \' ^( y4 i% J p. s! j. p
2 Z/ p# }: x7 h9 B4 }6 B<!-- 最大空闲时间, 当某个连接在这个时间内没活动后将从池中移除,前提是池中至少多于最少的连接数: minPoolSize --> 9 ~% z+ h0 ~7 T& ]5 x0 [' }
+ F; ] i% @# N; ~, S/ z8 W8 F6 u<property name="maxIdleTime" value="1800"/>
6 {/ G* t* W! H4 t7 |0 W& w1 M0 U( B+ T# ^
<!-- 为加强准备语句的执行性能,此参数指定被缓存的 PreparedStatement 的个数 --> 1 ~- F6 K: j4 q7 a/ T/ d/ p
4 ^7 ?5 h. }+ w, `* X P
<property name="maxStatements" value="50"/>
- O7 _/ R2 w# O) s
5 @7 j1 e# Q1 E</bean>
. D7 f0 f; S2 P, M' J$ }% A) B
$ v3 v) v9 C/ M7 ]( J* E2 q" g
; R% b2 M+ F; m. p% h% p; ~5 x8 l# [1 T$ k) {
Hibernate 会话厂 SessionFactory
* |4 P; C6 w$ N( ^! `- z; p0 V" \, {* }. l# {
Session 就是用于每次与数据库会话的,因此需要:
+ p9 h) N' T2 j2 G, i. |
% k8 `' h! m* T$ u数据库的配置参数,这些参数就是 上面的数据源指定的! 因此我们只需引用即可: ref="dataSource"; # D; a( v4 N3 Z: T0 K
5 q0 M3 C9 W% m! _* p: i, K* u实体映射配置 hibernate.cfg.xml 配置
- U' X/ I+ o0 R+ [: O& _
4 l P( O! h7 ~/ m' h' ~. l结果缓存配置(这里使用的是开源的 ehcache)
5 ^ S/ Q: ]4 W
6 ] n$ h4 C2 B2 y& c p( k
3 U& ~! s$ ]/ o/ u9 f. R! P! n0 T; r) b2 Y: _8 n$ |
<!-- Hibernate SessionFactory -->
& V/ g- i% _! s3 s7 t% F$ U/ j1 |( A5 B& x
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> & |9 H( z% R1 G. u g: _$ X0 m, H
; f7 `& ?4 `6 @' f& T& S
<!-- 引用前面定义的数据源 -->
2 f8 m1 F( u1 p, l
- [7 K) }% p1 h5 T1 D( i' h<property name="dataSource" ref="dataSource"/> ( ^9 {3 w. R* D- D# H) V
8 Q2 F" \, R- x1 F7 z2 L; k9 W3 b& H' R<!-- 所有实体映射文件列表, 所有的 hbm.xml 文件 -->
0 }# H M! B( s) I* U5 C" j" S6 c" P4 ~; g& p& ~4 d( s; e
<property name="mappingResources"> " X2 V- Y" \) U! [. }2 L. h5 ]( C7 A' H
" w. B0 s2 N% x. `* S( F+ d( m* t<list> 4 S1 T( D/ d) ?8 y6 p- I
% j8 N. \' N% }' {+ x6 k/ M" t
<value>org/springframework/samples/jpetstore/domain/Account.hbm.xml</value> & e3 z0 A2 ^6 p6 Z& w' w
, h* c% [1 Y. D<value>org/springframework/samples/jpetstore/domain/Banner.hbm.xml</value> ' G6 {% F. f8 N7 r. [0 S# n
8 p4 E9 {. ~, a% A* j* Z ^! b, p( Y. Q<value>org/springframework/samples/jpetstore/domain/Category.hbm.xml</value>
" C# f% Z3 y( x [6 h' {: x+ o$ x, x/ c3 `8 y% f) B) V, p2 `
<value>org/springframework/samples/jpetstore/domain/Inventory.hbm.xml</value> # N" _" E; f3 F& x
7 w( _$ T( D4 \<value>org/springframework/samples/jpetstore/domain/Item.hbm.xml</value>
; a8 J, p8 B- Z( Y. \, j
2 { J2 `8 z I/ }( L<value>org/springframework/samples/jpetstore/domain/LineItem.hbm.xml</value> ( A- p7 _$ A9 S- y
6 t w3 `, L8 u+ S+ X& S
<value>org/springframework/samples/jpetstore/domain/Order.hbm.xml</value>
7 |( h% p6 \# q: `, J+ L1 z7 z& B
<value>org/springframework/samples/jpetstore/domain/Product.hbm.xml</value>
8 T! `% [) ? ]( v% w1 c
2 f9 p5 ^% O' g! o<value>org/springframework/samples/jpetstore/domain/Supplier.hbm.xml</value> 9 L8 O; S% i8 }. P5 f; a9 w* e3 w
. W3 a! q1 |1 I6 f' r6 S$ X8 N9 _
</list>
8 V# N" K+ c4 j9 o
$ N( v! h! V7 A/ Q1 }9 C</property>
3 d9 [2 ~0 _3 T9 Q, c' F& |& _- I% c$ g0 U8 _
<!-- 传统上的 hibernate.cfg.xml 文件的参数放在这里 -->
6 o" u* {- {# d+ L. t3 f* y
' r+ C, A) X8 E5 ]/ j/ O<property name="hibernateProperties"> 3 {/ b2 `0 z+ w1 k+ W, R
8 \) ?0 r. g$ i P* }) P% L' ^# N/ B<props> ) s$ Q& O4 ]" ~5 p1 r) F/ l2 s
% `3 [# ], } f' o/ K4 Z! X) x5 b4 a
<!-- 指定数据库方言 -->
- }2 ~7 K; e8 |! Q6 a
! e a, Y( k; R9 v1 N( r; z<prop key="hibernate.dialect">${hibernate.dialect} & P# b- C5 G$ ~8 d6 d, P0 U
6 x- i C: N& n+ [& V: u/ C
</prop>
4 D( n/ \6 g9 |) T/ u ~% ~! e4 X1 x2 _9 E
<!-- 是否在日志中输出所有Hibernate与数据库交互的SQL语句 --> 4 \5 o# c9 y9 w A& e5 _) Q
$ _% Y% ~$ z- N3 Y
<prop key="hibernate.show_sql">true</prop>
8 r9 N# ?& i& C, K& M) G E$ ]/ Y
) X( D3 L; {$ V+ f( c<!-- 是否在日志中输出的SQL 语句格式化成易读形式 -->
( @, Q, `. a$ h! v( |$ l$ y [+ E9 t4 _
<prop key="hibernate.format_sql">true</prop> 5 j/ g" l% C% i% v1 p1 G) W$ G
9 ?4 } i' G+ H/ O2 T
<!-- 是否显示统计形式,一般在测试阶段使用 --> 6 {( p6 r n M4 a
o7 h* D. `. K: |+ |. B& u<prop key="hibernate.generate_statistics">true</prop>
: `: h5 Y- H" p6 a% q
; V8 Z2 V4 x; M( h: j ]6 R9 P3 a<!-- 对于级联查询,一次性获取的级联深度, @todo 需进一步研究 --> / [* Q( G/ g6 D! {" P/ a3 o- N
7 x% _3 ^6 _: ?0 N3 e8 z; O<prop key="hibernate.max_fetch_depth">2</prop>
Y* P5 s; R+ @2 v: R2 _1 ~) s/ P" S' G+ ^6 e# m3 s& l- V
<!-- 8 s# D5 `! O- I* z
: J# g& Q+ o+ ?, _5 S( {$ ?9 l. t
Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数,一般设置为30、50、100。
' Y3 l) J8 N/ T8 ^6 O8 k6 Y3 J
+ G% s S5 @: ]) b; D) {3 E5 iOracle数据库的JDBC驱动默认的Fetch Size=15,设置Fetch Size设置为:30、50,性能会有明显提升,如果继续增大,
$ T. U* M Q. @0 q" `8 t, f; p: b9 Z1 i+ X
超出100,性能提升不明显,反而会消耗内存。 8 O- c! |. \& e. t/ a( }7 o
" f3 ^5 K) c1 c$ W-->
8 [. D$ Z) y( q/ A
3 s/ D' R" m0 o" v) ^! G# u<prop key="hibernate.jdbc.fatch_size">100</prop> ) L1 @% C7 Z: B6 v
1 F, p* }3 t; d5 \9 R
<!-- 2 R B4 |9 R6 Q2 Q& J+ Y$ d
8 V; ^/ b, _" P8 E不必等到累计到50个SQL之后才执行.只要事务commit后,不管缓存中有多少条sql语句都要执行.
o3 w; X. O* E3 Q* A0 D% O- |: C5 x" |* E- h$ A' Z
hibernate.jdbc.batch_size参数只是设定一次最多可以提交多少sql语句的上限,提高sql语句的执行效率
4 W/ d% G8 a9 U4 g5 ]
( W8 z: L# b7 w) V--> / M! `0 a2 R" q4 `1 D
3 J& h7 h% p8 A
<prop key="hibernate.jdbc.batch_size">50</prop> 7 |6 m% c6 _* g) {1 D* ~' Y$ I+ ~
; s% t; H( X# C [) v9 |1 t
<!--
1 F2 E9 f% b; p- f! O9 Z, @" i* j
+ k& g( U5 f* j( N( @2 ~) C2 m r# t(1)create 在每次SesstionFactory 构建时(一般是应用重启时,或者伴随着应用服务器重启时),先将之前数据库中的所有数据全 - W4 v/ K+ `6 R2 Y
4 R$ Z& J- x3 W$ u& \
部清空,后紧跟着根据所有的hbm.xml 映射文件重新创建新的数据库表 ! g/ |/ _! C- k0 p% f8 D$ p
1 S: a, {0 y/ K, z Q
0 R Y7 g: ?. z l+ \$ X5 H, t/ B- I. g, f4 p& F& R4 Z
(2)create-drop 除了create 的所有含义之外,在每次应用的退出前,将进行一次数据空清空。因此这个配置将有两次清空操作, $ f! S) D2 p O+ X6 |& e5 q
$ [" J$ j9 ^, Q) ^, M$ `, T
一次是退出,一次是启动时。
: F2 i' w3 y& a9 F3 x& u8 r; k* `4 `- V I
) m4 c( b5 ]5 ]8 p
/ \3 X: a9 @& F. C" Z, D, b* m(3)update & J7 A N1 g0 Z2 K0 i' A2 ]
4 s% `: Z# r* _
如果在开发阶段理发了实体对象的映射文件(hbm.xml) 的定义后,此配置将后台的数据库表进行更新(如增加表的列) . Y7 ]; J* y4 p! z, {. `
7 Q+ L5 F8 R+ w, \. J; O! E' [5 {
2 ?' Y& T/ s6 D. f' @, q: r# C3 x
7 ?4 T- w* z) ?( V# d(4)validate + e) B& A5 g# h+ ~2 U" i
& u# [6 P L8 }. e, p, s5 W* Z) v用于校验现有的表与现有的配置是否一致。
9 B! O- M5 n5 C$ o8 j8 i& Y+ a
8 b- D+ L6 D0 X7 ? {4 Z-->
7 F) L0 b" Z5 y0 _) _, u5 v8 D2 y( ?2 n& R! m: m
<prop key="hibernate.hbm2ddl.auto">update</prop> . S+ j8 y" z2 \. `4 w+ K
. E/ e% [0 Q) _9 i; {3 d& O! R$ ^
<!-- 见下面的解释 -->
. W5 b3 q* j/ v
' Q4 D; k( e9 `& [<prop key="hibernate.hbm2ddl.auto">update</prop> 3 }- c; h/ B; u! ^) F f
0 k( f2 a4 j+ o; e; q0 R
<!--结果缓存配置:- 将ehcache.xml 置于 classpath 中- 如果不设置“查询缓存”,
4 t1 E4 |5 M) T% J0 M" k* @3 f; ?, `% K1 }+ v' c. m% s; t+ Y: V
那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、 list()、
/ |1 A1 {- P l! x' J+ S% @" s
) W" {1 o5 ]2 h! _" k+ hIterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置
% ?. P$ G, i6 A' I. w' e9 e& \ ^* O5 W E* J
hibernate.cache.use_query_cache true 才行- 在Hbm文件中添加<cache usage="read-only"/>- 3 A4 Q% a4 {* q" N6 [
" ^; @- h. L1 _; N h- ?& u4 y
如果需要“查询缓存”,还需要在使用Query或Criteria()时设置其setCacheable(true);属性--> # Z( |: O# j. h1 M
- H* p$ g* V; l9 B
<prop key="hibernate.cache.use_query_cache">true</prop> ) S: b2 S; z. _/ U5 y( z$ t
# g) W6 P% m' f$ D1 T% y<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> 3 k }$ S9 t1 ]" v ^- G- M( C
- c$ N V: r. b1 p/ D3 i: @
</props>
, d6 N# [3 n1 v
) e7 N) V i6 q</property> / r$ X Y: t1 h7 B2 j
; @& q. a% G# t' E% q<!-- 为解决 merge()方法语义的歧义 @todo 以后进一步解析或者你可以看一下相应的文档 -->
9 q$ m1 o+ Z9 H* z& [
% K) K. p2 N( B' [: m, X( D<property name="eventListeners">
0 \, B4 D3 y- _' ^* R: Q
6 T4 j% h' @0 |2 k" }<map><entry key="merge">
( u$ u' t' w. p: }. {
, R& {! @* h+ I$ N5 \- W<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
4 b/ w- e. ]) @% g/ t: s$ _* G
4 c1 p* H$ Y( J</entry></map>
: _. Z1 C) T: q# X- c9 M' ~6 |7 e; P2 ]6 D
</property> / B O" m) {7 M2 @: C% b7 k8 }0 i
6 B% m" y/ `9 b# s. `7 Q- V7 q4 G
</bean>
. g+ G9 g) W$ W O& V+ U% [8 C( }& y" d
) i' n6 i z# \' M! F; @# z
( i7 J1 o9 n: {2 n E$ x) G; O
2、Spring的transactionAttributes
( n1 |. N* D! C J b$ k/ `2 s5 X5 r# g }2 \% Y
8 [1 b" h% k6 ~% O& R
% X; S" V% R9 P' H8 _; nPROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
1 Z* p8 [: Y1 @! e, [# q- y2 x
, l1 |$ q* E2 c2 w0 c3 L) sPROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
" G: [- W; N) q5 N9 ? x1 o: d) J3 W$ ~# n) k8 r; W6 G- m) w
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。 * u# U* a8 D6 S$ Z. P& v
8 y7 r' R W4 U/ UPROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
7 f8 c: u; C8 d1 H
# B$ H! L) E+ E7 Y5 vPROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
' F6 l! l, x) G$ m# K
( R: b, V" y5 d+ k/ OPROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
1 D& e, y+ B9 k
, }2 w8 w% p; o; CPROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 |
|