Domain å±?/span>
ç›®å‰ Grails åªæä¾›äº†åœ¨æ™®é€?Spring 应用ä¸ç‹¬ç«‹ä‹Éç”?GORM 的方法(现在 Groovy å’?Grails 已是
SpringSource 旗下的äñ”å“了åQŒè‡ªç„¶è¦é¦–先对自家äñ”å“æä¾›æ”¯æŒï¼‰ã€‚丘q‡ç›¸ä¿¡ä»¥åŽåœ¨å…¶å®ƒ Java EE 框架ä¸ä¹Ÿå¯ç‹¬ç«‹ä‹Éç”?GORMã€?
åœ?Grails 以外使用 GORMåQŒåªéœ€åœ?Domain ¾cÖM¸Šä½¿ç”¨ grails.persistence.Entity 注释å›_¯ã€‚其它的ž®±åƒåœ?Grails ä¸çš„ä¸€æ —÷€?/p>
在酾|®æ–¹é¢ä¹Ÿå¾ˆç®€å•,åªè¦ä½¿ç”¨ <gorm:sessionFactory ... /> å›_¯ã€‚详¾l†è¯·è§?Grails çš?PetClinicåQŒè¿™é‡Œå°±ä¸æ‹—˜qîCº†ã€?/p>
Controller å±?/strong>
å?Domain å±‚ä¸€æ øP¼ŒController 层也全部使用 Groovy å®žçŽ°ã€‚ä¸»è¦æ˜¯å› 䨓 GORM 的大部分æ–ÒŽ³•都是动æ€çš„ã€?
1. ClinicController: ClinicController 实现äº?InitializingBean 接å£ã€‚这个接å£åªæœ‰ä¸€ä¸ªæ–¹æ³?afterPropertiesSet。这个方法会åœ?Bean 完æˆå±žæ€§è®¾¾|®ä¹‹åŽæ‰§è¡Œã€‚PetClinic 用这个方å¼å®žçŽîCº†¾cÖM¼¼ Grails ä¸?BootStrap 的部分功能。在˜q™ä¸ªæ–ÒŽ³•䏿ˆ‘们å¯ä»¥çœ‹åˆ?GORM ä¸çš„ save() æ–ÒŽ³•å’? addTo* åŠ¨æ€æ–¹æ³•都是å¯ç”¨çš„ã€?/p>
å¯èƒ½æœ‰äh会问åQŒafterPropertiesSet()
˜q™ä¸ªæ–ÒŽ³•çš„ä½œç”¨å°±æ˜¯å¢žåŠ ä¸€äº›é¢„å®šä¹‰çš„æ•°æ®ï¼Œä¸ÞZ»€ä¹ˆä¸ä½¿ç”¨æž„é€ å‡½æ•°æ¥å®žçŽ°ã€‚å®žé™…ä¸ŠåQŒåœ¨æœ¬ä¾‹ä¸ï¼ŒafterPropertiesSet()
的作用的¼‹®å¯ä»¥ç”¨æž„é€ å‡½æ•°æ¥å®žçްåQˆç»˜q‡æµ‹è¯•)。至于作者是å‡ÞZºŽä»€ä¹ˆç›®çš„而选择了实çŽ?InitializingBean æŽ¥å£æˆ‘也说ä¸å¥½ã€?br />
ClinicController 的其它部分就是一些简å•çš„ä¸èƒ½å†ç®€å•çš„ Http è¯äh±‚处ç†å‡½æ•°äº†ã€‚需è¦è¯´æ˜Žçš„一ç‚ÒŽ˜¯ @RequestMapping ä¸çš„å€ég»£è¡¨äº†è¯äh±‚çš?URLåQŒè¿™ä¸ªæ˜¯ä¸ç”¨å¸¦å޾~€çš„,也就是说 ".do" 是多余的ã€?br />
2. AddPetForm:
åœ?AddPetForm ¾cÈš„¾U§åˆ«ä¸Šæœ‰ä¸‰ä¸ªæ³¨é‡ŠåQŒåˆ†åˆ«æ˜¯ @Controller, @RequestMapping å’?
@SessionAttributes。@Controller ä¸ç”¨å¤šè¯´åQŒä½œç”¨æ˜¯˜q™ä¸ª¾cÕd£°æ˜Žäؓ一ä¸?Spring ControlleråQŒåƈæ·ÕdŠ åˆ?
Context ä¸ã€‚下é¢ä»‹¾l一ä¸?@RequestMapping å’?@SessionAttributes 的功能:
除æ¤ä»¥å¤–åQŒAddPetForm ä¸è¿˜æœ‰ä¸¤ä¸ªç‰¹ŒDŠçš„æ–ÒŽ³•åQŒä¸€ä¸ªæ˜¯æ³¨é‡Šäº?@ModelAttribute 的方法;å¦ä¸€ä¸ªæ˜¯æ³¨é‡Šäº?@InitBinder 的方法。下é¢åˆ†åˆ«ä»‹¾l一下:
Controller 层ä¸ä¸¤ä¸ªç‰ÒŽ®Šçš„ç±»åQšClinicBindingInitializer å’?PetTypeEditor
é…ç½®
1. applicationContext.xml
applicationContext ä¸å¤§éƒ¨åˆ†éƒ½æ˜¯å¸¸è§çš?Spring é…置。特ŒDŠä¸€ç‚¹çš„é…置除了 <gorm:sessionFactory ... /> 以外åQŒè¿˜æœ?Hibernate StatisticsService JMX 的酾|®ã€?/p>
2. dispatcher-servlet.xml
Spring MVC é…置文äšgåQˆä¹Ÿæ˜¯ä¸€ä¸?Spring 的酾|®æ–‡ä»Óž¼‰çš„é»˜è®¤åæ˜?dispatcher-servlet.xmlã€?/p>
从上至下åQŒç¬¬ä¸€ä¸ªé…¾|®è¡¨æ˜Žå“ªä¸?Package 下的 Class 使用äº?Spring çš?@Controller
注释。这æ ?Spring 容器在å¯åŠ¨çš„æ—¶å€™ä¼šè‡ªåŠ¨æ‰«æå…¶ä¸‹çš?ClassåQŒå°†åŠ æ³¨äº?@Controller æ³¨é‡Šçš„ç±»åŠ å…¥åˆ?Spring
的容器ä¸ã€?
½W¬äºŒä¸ªé…¾|?DefaultAnnotationHandlerMapping æ˜?HandlerMapping 接å£çš„ä¸€ä¸ªæœ€å¸¸ç”¨çš„å®žçŽ°ç±»ã€‚ç”¨äºŽæ˜ ž®?Handler 和请求èµ\径之间的关系。通过˜q™æ ·çš„é…¾|®ï¼ŒController ä¸çš„ @RequestMapping ä¸çš„路径值就å¯ä»¥çœŸæ£åœ°å’Œ Http è¯äh±‚对应èµäh¥ã€‚HandlerMapping çš„å¦å¤–一个常用的实现¾cÀL˜¯ ControllerClassNameHandlerMapping ã€?/p>
½W¬ä¸‰ä¸ªé…¾|?AnnotationMethodHandlerAdapter 的作用是使处ç†è¯·æ±‚çš„ Handler 能够真æ£çš„具有处ç†è¯·æ±‚的能力而æä¾›ä¸€äº›æœåŠ¡ï¼ŒåŒ…æ‹¬ä¸ø™¯·æ±‚傿•°ç»‘定应用相应的属性编辑器åQˆé€šè¿‡æ³¨å†Œ webBindingInitializer 实现åQ‰ã€?/p>
==============================¾l“æŸçš„分割线==============================
写到˜q™é‡ŒåQŒPetClinic-MVC ä¸å€¼å¾—分æžå¦ä¹ 的代ç 都æåˆ°äº†ã€‚PetClinic-MVC 是一个很ž®çš„应用åQŒä½†æ˜¯å…¶ä¸æ¼”½CÞZº† GORM 在普é€?Spring ä¸çš„应用å’? Spring MVC 2.5 çš„ä‹É用。细看的è¯è¿˜æ˜¯èƒ½å¦åˆ°ä¸å°‘ä¸œè¥¿çš„ã€‚æˆ‘æ‰€å†™çš„åªæ˜¯æˆ‘çš„ç†è§£åQŒéš¾å…会有一些丑›_’Œé”™è¯¯åQŒæ¬¢˜qŽçº æ£ã€?/span>
本文ž®†ç®€å•谈谈我å¯?EJB 3.0 的两¿U?Persistence Context å’?Seam-managed Persistence Context çš„ä¸åŒç‚¹çš„ç†è§£ã€æ‰€è¦è§£å†³çš„问题和我自己所疑惑的问题ã€?br />
EJB 3.0 (JPA) çš?Persistence Context
大家在ä‹Éç”?EJB 3.0 的时候会注æ„åˆ?EJB 3.0 ä¸çš„容器½Ž¡ç† Persistence Context
有两¿U类型,一¿U是 TransactionåQŒå¦ä¸€¿U是 Extended。这是一个较 Hibernate çš?Session
所没有的概念,Session 没有两ç§ä¸åŒçš„类型,而且最é‡è¦çš„æ˜¯ Session 䏿˜¯å®¹å™¨½Ž¡ç†çš„,˜q™é‡Œçš„容器指的是 App Server
容器。这里暂时ä¸è°ˆè®º Persistence Context ä¸?Session 之间的异åŒï¼Œä¸»è¦è°ˆè°ˆä¸¤ç§ Persistence
Context 之间的ä¸åŒã€‚妘q?ORM çš„åŒå¦éƒ½çŸ¥é“åQŒå½“ Persistence Context 是打开状æ€çš„æ—¶å€™ï¼ŒModel
ž®±å¤„于被½Ž¡ç†çš„状æ€ä¸åQ›å½“ Persistence Context å…³é—之åŽåQŒModel ž®±å¤„于了 Detached 状æ€ã€?br />
上题q™äº›ç‰ÒŽ€§å¯¹äº?Transaction æˆ?Extended çš?Persistence Context
都是一æ ïLš„åQŒä¸åŒçš„地方在于 Persistence Context 何时被打开关é—。由于ç»å¤§å¤šæ•°æƒ…况下 Persistence Context
是被容器½Ž¡ç†çš„ï¼ˆå¦‚æžœä½ ä¸å«Œç¯ä¹Ÿå¯ä»¥è‡ªå·±æŽ§åˆ?Persistence ContextåQ‰ï¼Œæ‰€ä»¥åœ¨ EJB 3.0 应用ä¸çœ‹ä¸åˆ°æ‰“开或关é—?
Persistence Context 的代ç (Spring + Hibernate çš„åº”ç”¨ä¹ŸåŒæ ·å¦‚æ¤åQŒHibernate Session
的管ç†å·¥ä½œå¯ä»¥äº¤¾l?Spring æ¥åšåQ‰ã€?/p>
其实åQŒTransaction å’?Extended Persistence Context
çš„ä¸åŒä¹‹å¤„也ž®±åœ¨äºŽå®¹å™¨ä½•时打开或关é—?Persistence Context。Transaction ¾cÕdž‹çš?Persistence
Context çš„æ‰“å¼€å’Œå…³é—æ˜¯å’Œäº‹åŠ¡çš„æ‰“å¼€å’Œå…³é—æ˜¯åŒæ¥çš„。也ž®±æ˜¯è¯´åœ¨ä¸€ä¸ªäº‹åС开始之åŽï¼ŒPersistence Context
æ‰ä¼šå¼€å§‹ï¼›åœ¨äº‹åС关é—的时候,相应çš?Persistence Context 也会被关é—ã€?br />
Extended ¾cÕdž‹çš?Persistence Context çš„æ‰“å¼€å’Œå…³é—æ˜¯å’?Stateful Session Bean
çš„ç”Ÿå‘½å‘¨æœŸåŒæ¥çš„åQŒæ˜¯è·¨è¶Šäº‹åŠ¡çš„ã€‚ä¹Ÿž®±æ˜¯è¯ß_¼Œä»?SFSB çš„åˆå§‹åŒ–开始,直到销æ¯ï¼ŒPersistence Context
都是å˜åœ¨çš„ã€‚ä½ å¯ä»¥åœ¨äº‹åŠ¡ä¹‹å¤–æ‰§è¡Œå†™æ“作åQŒä½†æ˜¯è¿™æ˜¯åƈä¸ä¼šæ‰§è¡ŒçœŸæ£çš„æ•°æ®åº“æ“作åQŒå†™æ“ä½œåªæ˜¯æ”‘Ö…¥äº†é˜Ÿåˆ—,直到下一个事务,写æ“作æ‰ä¼šçœŸæ£åœ°è¢«æ‰§è¡Œã€‚两者的
ä¸åŒ½Ž€å•说æ¥å°±æ˜?Extended Persistence Context å˜åœ¨çš„æ—¶é—´æ›´é•Ñ€‚é‚£ä¸ÞZ»€ä¹ˆè¦æœ‰ä¸¤¿Uä¸åŒçš„ Persistence
Context 呢?
当一�Web
è¯äh±‚åˆ°æ¥æ—Óž¼ŒæœåŠ¡å™¨ä¼šæ‰“å¼€ä¸€ä¸ªçº¿½E‹ï¼Œ˜q™ä¸ª¾U¿ç¨‹å¯èƒ½ä¼šè°ƒç”¨ä¸€ä¸ªäº‹åŠ¡æ–¹æ³•ï¼Œ˜q™æ˜¯ä¸€ä¸ªäº‹åŠ¡ä¾¿å¼€å§‹äº†åQŒå½“˜q™ä¸ªè¯äh±‚¾l“æŸæ—Óž¼Œ¾U¿ç¨‹å…³é—åQŒäº‹åŠ¡ä¹Ÿéšä¹‹¾l“æŸã€‚ç”±äº?
Transaction ¾cÕdž‹çš?Persistence Context 的生å˜å‘¨æœŸæ˜¯åœ¨äº‹åŠ¡èŒƒå›´ä¹‹å†…çš„åQŒæ‰€ä»¥ä¸€ä¸?Web
è¯äh±‚的结æŸä¹Ÿæ„味ç€ç›¸åº”çš?Persistence Context 的关é—。由于多æ•?Web 应用在一‹Æ?Web
è¯äh±‚内å³å¯å®Œæˆä¸€ä¸ªç‹¬ç«‹çš„æ“ä½œåQŒæ‰€ä»¥å¤§éƒ¨åˆ†æƒ…况ä¸?Transaction çš?Persistence Context
æ˜¯é€‚ç”¨çš„ã€‚ä½†æ˜¯å¯¹äºŽä¸€äº›å¤æ‚的应用åQŒä¸€‹Æ¡æ“作需è¦è·¨‘Šå¤š‹Æ¡è¯·æ±‚。这¿U情况下åQŒå¦‚æžœä¾æ—§ä‹Éç”?Transcation çš?Persistence
ContextåQŒç”±äºŽæ¯‹Æ¡è¯·æ±‚结æŸåŽåQŒç›¸åº”çš„ Persistence Context 都被关é—åQŒç›¸åº”çš„ Model 也就å˜äØ“ Detached
状æ€ã€‚如果接下æ¥çš„请求ä»ç„‰™œ€è¦è¿™äº›å·²¾lå˜ä¸?Detached 状æ€çš„ Model ž®±éœ€è¦é‡æ–?loadåQŒä‹Éç”?merge()
æ–ÒŽ³•æ¥æŒä¹…åŒ–ã€‚ç¨æœ‰ä¸é€‚就会äñ”ç”?LazyInitializationException å’?
NonUniqueObjectExceptionã€‚åŒæ—Óž¼Œ˜q™ä¹Ÿæé«˜äº†æ“ä½œçš„å¤æ‚½E‹åº¦ã€?br />
如果使用 Extended Persistence Context ž®Þpƒ½è§£å†³˜q™äº›é—®é¢˜ã€‚ç”±äº?Extended
Persistence Context 的生命周期是ä¸?SFSB çš„ç”Ÿå‘½å‘¨æœŸåŒæ¥çš„åQŒæ‰€ä»¥åªè¦å¤š‹Æ¡è¯·æ±‚调用的都是åŒä¸€ä¸?SFSB
ä¸çš„æ–ÒŽ³•åQŒæœ‰å¤šå°‘‹Æ¡çš„è¯äh±‚åQŒPersistence Context æ€ÀL˜¯åŒä¸€ä¸ªï¼Œå…¶ä¸çš?Model 也始¾lˆæ˜¯è¢«ç®¡ç†çš„。很好地解决äº?
Persistence Context 在线½E‹ä¹‹é—´ä¼ 递的问题åQŒä¹Ÿä¸ä¼šæœ?LazyInitializationException å’?
NonUniqueObjectException 问题的å‘生ã€?br />
Seam-managed Persistence Context
EJB 3.0 容器½Ž¡ç†ä¹‹ä¸‹çš?Persistence Context
很ä¸é”™ï¼Œèƒ½è§£å†›_¾ˆå¤šé—®é¢˜ï¼Œä½†æ˜¯˜q˜æ˜¯æœ‰äº›é—®é¢˜æ— 法解决。Seam 很强大,如果有些问题 EJB 容器解决ä¸äº†äº†ï¼Œæ²¡å…³¾p»ï¼ŒæŠ?Persistence
Context 交由 Seam æ¥ç®¡ç†å°± OK 了。那 Seam 都能解决哪些 EJB ä¸èƒ½è§£å†³çš„问题呢åQŸå…ˆè€ƒè™‘下é¢ä¸¤ä¸ªé—®é¢˜åQ?/p>