{"id":13,"date":"2006-08-06T11:50:56","date_gmt":"2006-08-06T10:50:56","guid":{"rendered":"http:\/\/euve3303.vserver.de\/stefan\/blog\/?p=15"},"modified":"2011-12-02T20:36:03","modified_gmt":"2011-12-02T19:36:03","slug":"transaktionen-mit-hibernatesynchronizer-hibernate3-und-spring","status":"publish","type":"post","link":"https:\/\/cogito-ergo-blog.de\/blog\/2006\/08\/06\/transaktionen-mit-hibernatesynchronizer-hibernate3-und-spring\/","title":{"rendered":"Transaktionen mit HibernateSynchronizer, Hibernate3 und Spring"},"content":{"rendered":"<p>Will man Spring zusammen mit Hibernate 3 verwenden, so muss man beachten, dass die DataAccessObjects (DAOs) nicht ohne weiteres mit Spring zusammenarbeiten. Eine gute Spring-Integration ist aber w\u00fcnschenswert, weil man nur so in den Genuss der Spring-Features wie z.B. deklaratives Transaction-Management oder JTA-Transactions kommt.<\/p>\n<p>Ausserdem begegnet man bei der Verwendung von Hibernate 3 mit Sicherheit auch dem Lazy Loading, das seit Hibernate 3 per Default aktiviert ist. Dieses Feature sorgt daf\u00fcr, dass nicht sofort ben\u00f6tigte Datenbankinhalte beim &quot;Load&quot; gar nicht geladen werden, sondern erst dann wenn man sie tats\u00e4chlich braucht.<\/p>\n<p>Das funktioniert aber nur, wenn zu einem sp\u00e4teren Zeitpunkt &#8211; wenn dann\u00a0auf die Datenbank zugegriffen wird &#8211; die Hibernate-Session auch noch offen ist &#8230;<\/p>\n<p><!--more--><\/p>\n<h3>Session Management<\/h3>\n<p>HibernateSynchronizer kennt von Hause aus nur zwei verschiedene Arten des Session-Lifecycle:<\/p>\n<ol>\n<li>Implizite Sessions: Der RootBaseDAO verwaltet eine &quot;current&quot; Session und \u00f6ffnet und schlie\u00dft diese bei Bedarf.<\/li>\n<li>Implizite Session mit &quot;Deferred Close&quot;: durch \u00dcberschreiben der &quot;closeSession&quot; Methode im RootDAO wird das automatische Schliessen der Session verhindert.<\/li>\n<\/ol>\n<p>Die 2. Methode ist empfohlen, wenn &quot;Lazy Loading&quot; verwendet wird. Allerdings\u00a0muss sp\u00e4ter die Session\u00a0explizit durch &quot;closeCurrentSession&quot; geschlossen werden.<\/p>\n<p>Beide Modi 1 und 2 bieten allerdings keine Zusammenarbeit mit Spring-Managed-Transactions hier muss ein eigener RootBaseDAO integriert werden.<\/p>\n<p>HibernateSychronizer bietet diese Option an, wenn man in den Projekt-Einstellungen folgende \u00c4nderungen vornimmt:<\/p>\n<p><img decoding=\"async\" alt=\"options\" hspace=\"0\" src=\"http:\/\/www.lookingeye.de\/blog\/uploads\/hiber-opt.jpg\" align=\"baseline\" border=\"0\" \/><\/p>\n<h3>Der neue RootDAO<\/h3>\n<p>Die Implementierung des neuen RootDAO st\u00fctzt sich auf die urspr\u00fcngliche Implementierung, die HibernateSynchronizer mitbringt und die Klasse &quot;SessionFactoryUtils&quot; von Spring ab.<\/p>\n<p>Alle Aufrufe aus dem urspr\u00fcnglichen RootDAO, die Sessions \u00f6ffnen oder schliessen, werden nun an die Klasse SessionFactoryUtils delegiert.<\/p>\n<p>Dieser Code-Ausschnitt zeigt die betreffenden Methoden:<\/p>\n<blockquote style=\"border: 1px solid gray; font-family: courier new; font-size: 85%; background-color: rgb(238, 238, 238); overflow: auto; height: 300px;\">\n<pre><span class=\"java4\">public <\/span><span class=\"java10\">Session getSession<\/span><span class=\"java8\">() {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">if<\/span><span class=\"java8\">( <\/span><span class=\"java10\">deferredClose &amp;&amp; currentSession.get<\/span><span class=\"java8\">() <\/span><span class=\"java10\">!= <\/span><span class=\"java4\">null <\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java3\">\/\/ reuse session<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">return <\/span><span class=\"java10\">currentSession.get<\/span><span class=\"java8\">()<\/span><span class=\"java10\">.session;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">if<\/span><span class=\"java8\">( <\/span><span class=\"java10\">session != <\/span><span class=\"java4\">null <\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">return <\/span><span class=\"java10\">session;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">} <\/span><span class=\"java4\">else <\/span><span class=\"java8\">{<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java10\">Session s = SessionFactoryUtils.getSession<\/span><span class=\"java8\">(<\/span><span class=\"java10\">sessionFactory,true<\/span><span class=\"java8\">)<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">if<\/span><span class=\"java8\">( <\/span><span class=\"java10\">deferredClose <\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java10\">SessionFactoryUtils.initDeferredClose<\/span><span class=\"java8\">(<\/span><span class=\"java10\">sessionFactory<\/span><span class=\"java8\">)<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 currentSession.set<\/span><span class=\"java8\">(<\/span><span class=\"java4\">new <\/span><span class=\"java10\">SessionInfo<\/span><span class=\"java8\">(<\/span><span class=\"java10\">s,sessionFactory<\/span><span class=\"java8\">))<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">return <\/span><span class=\"java10\">s;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n\u00a0 }<br \/>\r\n<br \/>\r\n\u00a0 <\/span><span class=\"java4\">public <\/span><span class=\"java9\">void <\/span><span class=\"java10\">setSession <\/span><span class=\"java8\">(<\/span><span class=\"java10\">Session session<\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">this<\/span><span class=\"java10\">.session = session;<br \/>\r\n\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n<br \/>\r\n\u00a0 <\/span><span class=\"java14\">\/**<br \/>\r\n\u00a0\u00a0 &#42; Set the session factory<br \/>\r\n\u00a0\u00a0 &#42;\/<br \/>\r\n\u00a0 <\/span><span class=\"java4\">public <\/span><span class=\"java9\">void <\/span><span class=\"java10\">setSessionFactory <\/span><span class=\"java8\">(<\/span><span class=\"java10\">SessionFactory sessionFactory<\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">this<\/span><span class=\"java10\">.sessionFactory = sessionFactory;<br \/>\r\n\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n<br \/>\r\n\u00a0 <\/span><span class=\"java14\">\/**<br \/>\r\n\u00a0\u00a0 &#42; Return the SessionFactory that is to be used by these DAOs.\u00a0 Change this<br \/>\r\n\u00a0\u00a0 &#42; and implement your own strategy if you, for example, want to pull the SessionFactory<br \/>\r\n\u00a0\u00a0 &#42; from the JNDI tree.<br \/>\r\n\u00a0\u00a0 &#42;\/<br \/>\r\n\u00a0 <\/span><span class=\"java4\">public <\/span><span class=\"java10\">SessionFactory getSessionFactory<\/span><span class=\"java8\">() {<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">return <\/span><span class=\"java10\">sessionFactory;<br \/>\r\n\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n<br \/>\r\n<br \/>\r\n\u00a0 <\/span><span class=\"java14\">\/**<br \/>\r\n\u00a0\u00a0 &#42; Close all sessions for the current thread<br \/>\r\n\u00a0\u00a0 &#42;\/<br \/>\r\n\u00a0 <\/span><span class=\"java4\">public static <\/span><span class=\"java9\">void <\/span><span class=\"java10\">closeCurrentSession <\/span><span class=\"java8\">() {<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java10\">SessionInfo si = currentSession.get<\/span><span class=\"java8\">()<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">if <\/span><span class=\"java8\">(<\/span><span class=\"java4\">null <\/span><span class=\"java10\">!= si <\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java10\">SessionFactoryUtils.processDeferredClose<\/span><span class=\"java8\">(<\/span><span class=\"java10\">si.sessionFactory<\/span><span class=\"java8\">)<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 currentSession.set<\/span><span class=\"java8\">(<\/span><span class=\"java4\">null<\/span><span class=\"java8\">)<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n\u00a0 }<br \/>\r\n<br \/>\r\n\u00a0 <\/span><span class=\"java14\">\/**<br \/>\r\n\u00a0\u00a0 &#42; Close the session<br \/>\r\n\u00a0\u00a0 &#42;\/<br \/>\r\n\u00a0 <\/span><span class=\"java4\">public <\/span><span class=\"java9\">void <\/span><span class=\"java10\">closeSession <\/span><span class=\"java8\">(<\/span><span class=\"java10\">Session s<\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java4\">if<\/span><span class=\"java8\">( <\/span><span class=\"java10\">session == <\/span><span class=\"java4\">null <\/span><span class=\"java8\">) {<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java10\">SessionFactoryUtils.releaseSession<\/span><span class=\"java8\">(<\/span><span class=\"java10\">s,sessionFactory<\/span><span class=\"java8\">)<\/span><span class=\"java10\">;<br \/>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/span><span class=\"java8\">}<br \/>\r\n\u00a0 }<br \/>\r\n<br \/>\r\n\u00a0 <\/span>\r\n<\/pre>\n<\/blockquote>\n<p>Damit\u00a0nehmen alle DAO-Session automatisch an evtl. laufenden Transaktionen teil. Eine L\u00f6sung f\u00fcr das &quot;Lazy Loading&quot; ergibt sich so aber nur, wenn tats\u00e4chlich Transaktional gearbeitet wird. Hier bleibt die Session selbstverst\u00e4ndlich w\u00e4hrend der Transaktion offen.<\/p>\n<h4>Und ohne Transaktionen<\/h4>\n<p>Nun will man aber nicht unbedingt transaktional arbeiten\u00a0aber vielleicht dennoch &quot;Lazy Loading&quot; verwenden. Hierzu muss die Session aber offen bleiben. Ach hierf\u00fcr bietet die Spring-Klasse Support\u00a0an: initDeferredClose und processDeferredClose.<\/p>\n<p>Welche Art des Session-Handlings man benutzen will, kann man nun wie bei HibernateSynchronizer durch \u00dcberschreiben einer Methode\u00a0kl\u00e4ren, die das eine oder andere Verhalten festlegt.<\/p>\n<p>Alternativ kann man das Session-Handling auch zur Eigenschaft der DAOs machen, um so maximale Flexibilit\u00e4t zu erhalten.<\/p>\n<p>So l\u00e4sst sich einstellen, ob ..<\/p>\n<ol>\n<li>Sessions implizit durch die Transaktion definiert werden.<\/li>\n<li>Sessions implizit ge\u00f6ffnet und (bald) wieder geschlossen werden.<\/li>\n<li>Sessions lange offen gehalten werden (f\u00fcr Lazy-Loading) und sp\u00e4ter explizit geschlossen werden m\u00fcssen.<\/li>\n<\/ol>\n<p \/>\n","protected":false},"excerpt":{"rendered":"<p>Will man Spring zusammen mit Hibernate 3 verwenden, so muss man beachten, dass die DataAccessObjects (DAOs) nicht ohne weiteres mit Spring zusammenarbeiten. Eine gute Spring-Integration ist aber w\u00fcnschenswert, weil man nur so in den Genuss der Spring-Features wie z.B. deklaratives &hellip; <a href=\"https:\/\/cogito-ergo-blog.de\/blog\/2006\/08\/06\/transaktionen-mit-hibernatesynchronizer-hibernate3-und-spring\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"_links":{"self":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/13"}],"collection":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=13"}],"version-history":[{"count":1,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions"}],"predecessor-version":[{"id":10013,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions\/10013"}],"wp:attachment":[{"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cogito-ergo-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}