<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Dynamic DataSource Routing</title>
	<atom:link href="http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/</link>
	<description>The voice of SpringSource</description>
	<lastBuildDate>Fri, 19 Mar 2010 07:01:07 -0500</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Routing Datasources &#171; Pirack Blog</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-171496</link>
		<dc:creator>Routing Datasources &#171; Pirack Blog</dc:creator>
		<pubDate>Thu, 04 Mar 2010 06:00:03 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-171496</guid>
		<description>[...] The pure spring solution is described at The Spring Blog [...]</description>
		<content:encoded><![CDATA[<p>[...] The pure spring solution is described at The Spring Blog [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jithen</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-171059</link>
		<dc:creator>Jithen</dc:creator>
		<pubDate>Wed, 20 Jan 2010 19:25:08 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-171059</guid>
		<description>Its an amazing implementation to reduce app developers tasks. Thanks for publishing. I have a special requirement where I should load different hibernate mappings with each data source based on its key. Could anyone help me understand the approach? Regards.</description>
		<content:encoded><![CDATA[<p>Its an amazing implementation to reduce app developers tasks. Thanks for publishing. I have a special requirement where I should load different hibernate mappings with each data source based on its key. Could anyone help me understand the approach? Regards.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Product data Entry</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-169815</link>
		<dc:creator>Product data Entry</dc:creator>
		<pubDate>Thu, 03 Dec 2009 09:05:17 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-169815</guid>
		<description>Great post. The content here is really very informative.</description>
		<content:encoded><![CDATA[<p>Great post. The content here is really very informative.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: yanz</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-168612</link>
		<dc:creator>yanz</dc:creator>
		<pubDate>Wed, 30 Sep 2009 09:48:24 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-168612</guid>
		<description>Thank you for this great post. In my web applicaiton user related information is saved in session after user Logs In and i have to to decide datasource name based upon this information. How can i make httpsession available to custom data source resolver class. I&#039;m using Spring and Tapestry.</description>
		<content:encoded><![CDATA[<p>Thank you for this great post. In my web applicaiton user related information is saved in session after user Logs In and i have to to decide datasource name based upon this information. How can i make httpsession available to custom data source resolver class. I&#039;m using Spring and Tapestry.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ondrej Burkert</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-168520</link>
		<dc:creator>Ondrej Burkert</dc:creator>
		<pubDate>Tue, 22 Sep 2009 11:45:57 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-168520</guid>
		<description>Hi, 

I tried this approach and it works just fine but as we use Hibernate, the second level hibernate cache did not work. One of the possible solutions to this is to create separate session factory for each data source. But as the session factory object is quite resource demanding and the schema of the data sources were every time the same I tried to find a way around it. In the end we ended up by wrapping CacheProvider and adding our wrapper for the Cache to the system.

The main idea is to prefix cache entries by the data source identificators.

In steps:
1. Implement your AbstractRoutingDataSource and supply it to your Hibernate session factory as described in the blog entry.
2. Implement a wrapper to the CacheProvider which will contain field with CacheProvider implementation supplied from the Spring configuration for instance.
3. The methods of your CacheProvider are just delegating work to the underlying cache provider except for the buildCache method which creates the CacheWrappers:
  public Cache buildCache(String name, Properties properties) throws CacheException {
    Cache cache = cacheProvider.buildCache(name, properties);
    if (!(cache instanceof OKbaseCache)) {
      cache = new CacheWrapper(cache, dataSourceProvider);
    }
    return cache;
  }
4. Implement CacheWrapper - it implements interface org.hibernate.cache.Cache and it prefixes the keys of elements which are put/retrieved from the cache by a context based information:
for instance:
public class CacheWrapper implements Cache {
  
  private Cache underlyCache;
  
  public CacheWrapper(Cache underlyCache) {
    this.underlyCache = underlyCache;
  }
    
  @Override
  public void clear() throws CacheException {
    underlyCache.clear();
  }
....
  
  @Override
  public Object get(Object key) throws CacheException {
    return underlyCache.get(CustomerContextHolder.getCustomerType()   key));
  }
  
Every use of the &quot;key&quot; must be prefixed correspondingly. Of course it might be wise to define your own key which would work with the prefix (data source identification) and the &quot;Object key&quot; and would define correctly hashCode and equals...

In the end you have to inject your CacheProvider into the SessionFactory. 

The Hibernate second level cache will work as everytime a user connects to a given data source, he consults the region of cache prefixed with the data source identification, thus objects with same ID from different data sources would not clash.
  
Note, from Hibernate 3.3 the use of Cache interface is deprecated and we should use RegionFactory instead. But as most caches still work on the base of Cache interface, I guess it can wait to rewrite it to the version using RegionFactory rather than CacheProvider...</description>
		<content:encoded><![CDATA[<p>Hi, </p>
<p>I tried this approach and it works just fine but as we use Hibernate, the second level hibernate cache did not work. One of the possible solutions to this is to create separate session factory for each data source. But as the session factory object is quite resource demanding and the schema of the data sources were every time the same I tried to find a way around it. In the end we ended up by wrapping CacheProvider and adding our wrapper for the Cache to the system.</p>
<p>The main idea is to prefix cache entries by the data source identificators.</p>
<p>In steps:<br />
1. Implement your AbstractRoutingDataSource and supply it to your Hibernate session factory as described in the blog entry.<br />
2. Implement a wrapper to the CacheProvider which will contain field with CacheProvider implementation supplied from the Spring configuration for instance.<br />
3. The methods of your CacheProvider are just delegating work to the underlying cache provider except for the buildCache method which creates the CacheWrappers:<br />
  public Cache buildCache(String name, Properties properties) throws CacheException {<br />
    Cache cache = cacheProvider.buildCache(name, properties);<br />
    if (!(cache instanceof OKbaseCache)) {<br />
      cache = new CacheWrapper(cache, dataSourceProvider);<br />
    }<br />
    return cache;<br />
  }<br />
4. Implement CacheWrapper &#8211; it implements interface org.hibernate.cache.Cache and it prefixes the keys of elements which are put/retrieved from the cache by a context based information:<br />
for instance:<br />
public class CacheWrapper implements Cache {</p>
<p>  private Cache underlyCache;</p>
<p>  public CacheWrapper(Cache underlyCache) {<br />
    this.underlyCache = underlyCache;<br />
  }</p>
<p>  @Override<br />
  public void clear() throws CacheException {<br />
    underlyCache.clear();<br />
  }<br />
&#8230;.</p>
<p>  @Override<br />
  public Object get(Object key) throws CacheException {<br />
    return underlyCache.get(CustomerContextHolder.getCustomerType()   key));<br />
  }</p>
<p>Every use of the &#034;key&#034; must be prefixed correspondingly. Of course it might be wise to define your own key which would work with the prefix (data source identification) and the &#034;Object key&#034; and would define correctly hashCode and equals&#8230;</p>
<p>In the end you have to inject your CacheProvider into the SessionFactory. </p>
<p>The Hibernate second level cache will work as everytime a user connects to a given data source, he consults the region of cache prefixed with the data source identification, thus objects with same ID from different data sources would not clash.</p>
<p>Note, from Hibernate 3.3 the use of Cache interface is deprecated and we should use RegionFactory instead. But as most caches still work on the base of Cache interface, I guess it can wait to rewrite it to the version using RegionFactory rather than CacheProvider&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Manish</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-168012</link>
		<dc:creator>Manish</dc:creator>
		<pubDate>Wed, 12 Aug 2009 20:43:53 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-168012</guid>
		<description>I tried implementing this , worked like a charm...Great Blog Mark !!</description>
		<content:encoded><![CDATA[<p>I tried implementing this , worked like a charm&#8230;Great Blog Mark !!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: HeeGu</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-167808</link>
		<dc:creator>HeeGu</dc:creator>
		<pubDate>Mon, 03 Aug 2009 17:43:32 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-167808</guid>
		<description>Hi, This is good article. Simple solution than JTA.

But this solution must be uses very carefully in multi-thread context. In SomeBOImpl, a method is exist to below.

   public void printAllItems() {
      printGoldItems();

      printSilverItems();
      
      printBronzeItems();
   }

   public void printGoldItems() {
      CustomerContextHolder.setCustomerType(CustomerType.GOLD);
      List goldItems = catalog.getItems();
      assertEquals(3, goldItems.size());
      System.out.println(&quot;gold items: &quot;   goldItems);
   }

   public void printSilverItems() {
      CustomerContextHolder.setCustomerType(CustomerType.SILVER);
      List silverItems = catalog.getItems();
      assertEquals(2, silverItems.size());
      System.out.println(&quot;silver items: &quot;   silverItems);
   }

   public void printBronzeItems() {
      CustomerContextHolder.clearCustomerType();
      List bronzeItems = catalog.getItems();
      assertEquals(1, bronzeItems.size());
      System.out.println(&quot;bronze items: &quot;   bronzeItems);              
   }

And two anonymous threads is runned printAllItems() after get SomeBOImpl in spring-context using BeanFactory at almost same time.

Is catalog.getItems() method run correctly as our wish?

Who is ThreadLocal&#039;s key? SomeBOImpl? or anonymous thread?</description>
		<content:encoded><![CDATA[<p>Hi, This is good article. Simple solution than JTA.</p>
<p>But this solution must be uses very carefully in multi-thread context. In SomeBOImpl, a method is exist to below.</p>
<p>   public void printAllItems() {<br />
      printGoldItems();</p>
<p>      printSilverItems();</p>
<p>      printBronzeItems();<br />
   }</p>
<p>   public void printGoldItems() {<br />
      CustomerContextHolder.setCustomerType(CustomerType.GOLD);<br />
      List goldItems = catalog.getItems();<br />
      assertEquals(3, goldItems.size());<br />
      System.out.println(&#034;gold items: &#034;   goldItems);<br />
   }</p>
<p>   public void printSilverItems() {<br />
      CustomerContextHolder.setCustomerType(CustomerType.SILVER);<br />
      List silverItems = catalog.getItems();<br />
      assertEquals(2, silverItems.size());<br />
      System.out.println(&#034;silver items: &#034;   silverItems);<br />
   }</p>
<p>   public void printBronzeItems() {<br />
      CustomerContextHolder.clearCustomerType();<br />
      List bronzeItems = catalog.getItems();<br />
      assertEquals(1, bronzeItems.size());<br />
      System.out.println(&#034;bronze items: &#034;   bronzeItems);<br />
   }</p>
<p>And two anonymous threads is runned printAllItems() after get SomeBOImpl in spring-context using BeanFactory at almost same time.</p>
<p>Is catalog.getItems() method run correctly as our wish?</p>
<p>Who is ThreadLocal&#039;s key? SomeBOImpl? or anonymous thread?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: à¹€à¸?à¸£à¸¥à¸ªà¹Œ à¸«à¸?à¸ªà¸´à¸šà¸«à¸? Â» à¸¡à¸²à¸—à¸³ dynamic datasource routing à¹ƒà¸™ grails à¸?à¸±à¸™</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-167664</link>
		<dc:creator>à¹€à¸?à¸£à¸¥à¸ªà¹Œ à¸«à¸?à¸ªà¸´à¸šà¸«à¸? Â» à¸¡à¸²à¸—à¸³ dynamic datasource routing à¹ƒà¸™ grails à¸?à¸±à¸™</dc:creator>
		<pubDate>Wed, 22 Jul 2009 07:39:50 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-167664</guid>
		<description>[...] Dynamic DataSource Routing Switchable Grails [...]</description>
		<content:encoded><![CDATA[<p>[...] Dynamic DataSource Routing Switchable Grails [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: NapiArgo</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-167228</link>
		<dc:creator>NapiArgo</dc:creator>
		<pubDate>Sun, 07 Jun 2009 08:00:09 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-167228</guid>
		<description>Hi Mark,

Thax alot, this solve my problem ;)</description>
		<content:encoded><![CDATA[<p>Hi Mark,</p>
<p>Thax alot, this solve my problem <img src='http://blog.springsource.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: å¤šæ•°æ?®åº“SaaSå°?è¯• &#171; OnlyLonely &#38; Marshall&#8217;s</title>
		<link>http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/comment-page-2/#comment-165356</link>
		<dc:creator>å¤šæ•°æ?®åº“SaaSå°?è¯• &#171; OnlyLonely &#38; Marshall&#8217;s</dc:creator>
		<pubDate>Tue, 05 May 2009 16:06:41 +0000</pubDate>
		<guid isPermaLink="false">http://blog.interface21.com/main/2007/01/23/dynamic-datasource-routing/#comment-165356</guid>
		<description></description>
		<content:encoded><![CDATA[<p>[...] Â Â Â  æŽ¥ä¸‹æ?¥å‡ å¤©æ„Ÿå†’å?‘çƒ§ï¼Œå¥½å¥½ä¼‘æ?¯äº†ä¸€é˜µå­?ï¼Œæ€?è·¯å?´æ‰“å¼€äº†ã€‚ä»Žç½‘ä¸Šé‡?æ–°æ?œå‡ºä¸€å †èµ„æ–™ã€‚è¿™ä¸ªæ˜¯Stack Overflowçš„ä¸€ä¸ªé—®ç­”ï¼Œå‡ ä¸ªå›žç­”éƒ½æ¯”è¾ƒé? è°±ï¼›è¿™ä¸ªæ˜¯é€šè¿‡HotSwappableTargetSourceæ??ä¾›çš„DataSourceåŠ¨æ€?æ›¿æ?¢ï¼›è¿™ä¸ªæ˜¯Springå¼€å?‘äººå‘˜åˆ©ç”¨AbstractRoutingDataSourceæ??ä¾›å¯¹DataSourceçš„è·¯ç”±ã€‚æ?ƒè¡¡å†?ä¸‰ï¼Œå†³å®šä½¿ç”¨AbstractRoutingDataSourceã€‚å?ªæ‰©å±•äº†ä¸¤ä¸ªç±»å°±æˆ?åŠŸå®žçŽ°åŠŸèƒ½ï¼Œä¸?æŠ›å¼‚å¸¸ã€‚å…¨å±€ä¸€ä¸ªSessionFactoryï¼Œå?Žé?¢å‡ ä¸ªDataSourceè½®æµ?ä¸Šã€‚ [...]</p>
]]></content:encoded>
	</item>
</channel>
</rss>
