首页 > 其他分享 >Spring 多数据源事务配置问题

Spring 多数据源事务配置问题

时间:2022-12-28 19:00:48浏览次数:40  
标签:事务 hibernate 数据源 springframework value Spring org import class


在SpringSide 3 中,白衣提供的预先配置好的环境非常有利于用户进行快速开发,但是同时也会为扩展带来一些困难。最直接的例子就是关于在项目中使用多个数据源的问题,似乎 很难搞。在上一篇中,我探讨了SpringSide 3 中的数据访问层,在这一篇中,我立志要解决多数据源配置的难题,我的思路是这样的:

第一步、测试能否配置多个DataSource
第二步、测试能否配置多个SessionFactory
第三步、测试能否配置多个TransactionManager
第四步、测试能否使用多个TransactionManager,也就是看能否配置多个

基本上到第四步就应该走不通了,因为Spring中似乎不能配置多个,而且@transactional注解也无法让用户选择具体使用哪个TransactionManager。也就是说,在SpringSide的应用中,不能让不同的数据源分别属于不同的事务管理器,多数据源只能使用分布式事务管理器,那么测试思路继续如下进行:

第五步、测试能否配置JTATransactionManager

如果到这一步,项目还能顺利在Tomcat中运行的话,我们就算大功告成了。但我总认为事情不会那么顺利,我总觉得JTATransactionManager需要应用服务器的支持,而且需要和JNDI配合使用,具体是不是这样,那只有等测试后才知道。如果被我不幸言中,那么进行下一步:

第六步、更换Tomcat为GlassFish,更换JDBC的DataSource为JNDI查找的DataSource,然后配置JTATransactionManager

下面测试开始,先假设场景,还是继续用上一篇中提到的简单的文章发布系统,假设该系统运行一段时间后非常火爆,单靠一台服务器已经无法支持巨大的用户数, 这时候,站长想到了把数据进行水平划分,于是,需要建立一个索引数据库,该索引数据库需保存每一篇文章的Subject及其内容所在的Web服务器,而每 一个Web服务器上运行的项目,需要同时访问索引数据库和内容数据库。所以,需要创建索引数据库,如下:


[java]  ​​view plain​​  ​​copy​​



  1. create database puretext_index;  
  2.   
  3. use puretext_index;  
  4.   
  5. create table articles(  
  6. id int primary key auto_increment,  
  7. subject varchar(256),  
  8. webserver varchar(30)  
  9. );  


第一步测试,配置多个DataSource,配置文件如下:
application.properties:


[java]  ​​view plain​​  ​​copy​​



  1. jdbc.urlContent=jdbc:mysql://localhost:3306/PureText useUnicode=true&characterEncoding=utf8  
  2. jdbc.urlIndex=jdbc:mysql://localhost:3306/PureText_Index useUnicode=true&characterEncoding=utf8  


applicationContext.xml:


[java]  ​​view plain​​  ​​copy​​



  1. < xml version="1.0" encoding="UTF-8" >  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" default-lazy-init="true" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  3.   
  4.     <description>Spring公共配置文件 </description>  
  5.   
  6.     <!-- 定义受环境影响易变的变量 -->  
  7.     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  8. "systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">  
  9. "ignoreResourceNotFound" value="true">  
  10. "locations">  
  11.             <list>  
  12.                 <!-- 标准配置 -->  
  13.                 <value>classpath*:/application.properties</value>  
  14.                 <!-- 本地开发环境配置 -->  
  15.                 <value>classpath*:/application.local.properties</value>  
  16.                 <!-- 服务器生产环境配置 -->  
  17.                 <!---->file:/var/myapp/application.server.properties -->  
  18.             <!--!----></list>  
  19.         </property>  
  20.     </property></property></bean>  
  21.   
  22. @Required,@Autowired的属性被注入 -->  
  23.     <context:component-scan base-package="cn.puretext">  
  24.   
  25.     <!-- 数据源配置,使用应用内的DBCP数据库连接池 -->  
  26. "dataSourceContent" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  27.         <!-- Connection Info -->  
  28. "driverClassName" value="com.mysql.jdbc.Driver">  
  29. "url" value="${jdbc.urlContent}">  
  30. "username" value="${jdbc.username}">  
  31. "password" value="${jdbc.password}">  
  32.   
  33.         <!-- Connection Pooling Info -->  
  34. "initialSize" value="5">  
  35. "maxActive" value="100">  
  36. "maxIdle" value="30">  
  37. "maxWait" value="1000">  
  38. "poolPreparedStatements" value="true">  
  39. "defaultAutoCommit" value="false">  
  40.     </property></property></property></property></property></property></property></property></property></property></bean>  
  41. "dataSourceIndex" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  42.         <!-- Connection Info -->  
  43. "driverClassName" value="com.mysql.jdbc.Driver">  
  44. "url" value="${jdbc.urlIndex}">  
  45. "username" value="${jdbc.username}">  
  46. "password" value="${jdbc.password}">  
  47.   
  48.         <!-- Connection Pooling Info -->  
  49. "initialSize" value="5">  
  50. "maxActive" value="100">  
  51. "maxIdle" value="30">  
  52. "maxWait" value="1000">  
  53. "poolPreparedStatements" value="true">  
  54. "defaultAutoCommit" value="false">  
  55.     </property></property></property></property></property></property></property></property></property></property></bean>  
  56.   
  57.     <!-- 数据源配置,使用应用服务器的数据库连接池 -->  
  58. "dataSource" jndi-name="java:comp/env/jdbc/ExampleDB">-->  
  59.   
  60.     <!-- Hibernate配置 -->  
  61. "sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  62. "dataSource" ref="dataSourceContent">  
  63. "namingStrategy">  
  64.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  65.         </bean></property>  
  66. "hibernateProperties">  
  67.             <props>  
  68. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  69. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  70. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  71. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  72.                 </prop>  
  73. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  74.             </props>  
  75.         </property>  
  76. "packagesToScan" value="cn.puretext.entity.*">  
  77.     </property></property></bean>  
  78.   
  79.     <!-- 事务管理器配置,单数据源事务 -->  
  80. "transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  81. "sessionFactory" ref="sessionFactory">  
  82.     </property></bean>  
  83.   
  84.     <!-- 事务管理器配置,多数据源JTA事务-->  
  85. "transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager or  
  86.         WebLogicJtaTransactionManager">  
  87.     -->  
  88.   
  89.     <!-- 使用annotation定义事务 -->  
  90. "transactionManager">  
  91. </tx:annotation-driven><!--!----><!--!--<jee:jndi-lookup--></context:component-scan></beans>  


这个时候运行上一篇文章中写好的单元测试DaoTest.java,结果发现还是会出错,错误原因如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cn.puretext.unit.service.DaoTest': Autowiring of methods failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests.setDataSource(javax.sql.DataSource); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: [dataSourceContent, dataSourceIndex]

经过分析,发现是测试类的基类需要注入DataSource,而现在配置了多个DataSource,所以Spring不知道哪个DataSource匹配了,所以需要改写DaoTest.java,如下:


[java]  ​​view plain​​  ​​copy​​



  1. package cn.puretext.unit.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import javax.annotation.Resource;  
  6. import javax.sql.DataSource;  
  7.   
  8. import org.junit.Test;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springside.modules.orm.Page;  
  11. import org.springside.modules.test.junit4.SpringTxTestCase;  
  12.   
  13. import cn.puretext.dao.ArticleDao;  
  14. import cn.puretext.entity.web.Article;  
  15.   
  16. public class DaoTest extends SpringTxTestCase {  
  17. @Autowired  
  18.     private ArticleDao articleDao;  
  19.       
  20.     public ArticleDao getArticleDao() {  
  21.         return articleDao;  
  22.     }  
  23.   
  24.     public void setArticleDao(ArticleDao articleDao) {  
  25.         this.articleDao = articleDao;  
  26.     }  
  27.   
  28. @Override  
  29. @Resource(name = "dataSourceContent")  
  30.     public void setDataSource(DataSource dataSource) {  
  31. // TODO Auto-generated method stub  
  32.         super.setDataSource(dataSource);  
  33.     }  
  34.   
  35. @Test  
  36.     public void addArticle() {  
  37.         Article article = new Article();  
  38. "article test");  
  39. "article test");  
  40.         articleDao.save(article);  
  41.     }  
  42.       
  43. @Test  
  44.     public void pageQuery() {  
  45.         Page<article> page = new Page<article>();  
  46. 10);  
  47. 2);  
  48.         page = articleDao.getAll(page);  
  49.         List<article> articles = page.getResult();  
  50.     }  
  51. }  
  52.   
  53. </article></article></article>  


改变的内容主要为重写了基类中的setDataSource方法,并使用@Resource注解指定使用的DataSource为dataSourceContent。经过修改后,单元测试成功运行。

第二步,配置多个SessionFactory,配置文件如下:


[java]  ​​view plain​​  ​​copy​​



  1. < xml version="1.0" encoding="UTF-8" >  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" default-lazy-init="true" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  3.   
  4.     <description>Spring公共配置文件 </description>  
  5.   
  6.     <!-- 定义受环境影响易变的变量 -->  
  7.     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  8. "systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">  
  9. "ignoreResourceNotFound" value="true">  
  10. "locations">  
  11.             <list>  
  12.                 <!-- 标准配置 -->  
  13.                 <value>classpath*:/application.properties</value>  
  14.                 <!-- 本地开发环境配置 -->  
  15.                 <value>classpath*:/application.local.properties</value>  
  16.                 <!-- 服务器生产环境配置 -->  
  17.                 <!---->file:/var/myapp/application.server.properties -->  
  18.             <!--!----></list>  
  19.         </property>  
  20.     </property></property></bean>  
  21.   
  22. @Required,@Autowired的属性被注入 -->  
  23.     <context:component-scan base-package="cn.puretext">  
  24.   
  25.     <!-- 数据源配置,使用应用内的DBCP数据库连接池 -->  
  26. "dataSourceContent" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  27.         <!-- Connection Info -->  
  28. "driverClassName" value="com.mysql.jdbc.Driver">  
  29. "url" value="${jdbc.urlContent}">  
  30. "username" value="${jdbc.username}">  
  31. "password" value="${jdbc.password}">  
  32.   
  33.         <!-- Connection Pooling Info -->  
  34. "initialSize" value="5">  
  35. "maxActive" value="100">  
  36. "maxIdle" value="30">  
  37. "maxWait" value="1000">  
  38. "poolPreparedStatements" value="true">  
  39. "defaultAutoCommit" value="false">  
  40.     </property></property></property></property></property></property></property></property></property></property></bean>  
  41. "dataSourceIndex" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  42.         <!-- Connection Info -->  
  43. "driverClassName" value="com.mysql.jdbc.Driver">  
  44. "url" value="${jdbc.urlIndex}">  
  45. "username" value="${jdbc.username}">  
  46. "password" value="${jdbc.password}">  
  47.   
  48.         <!-- Connection Pooling Info -->  
  49. "initialSize" value="5">  
  50. "maxActive" value="100">  
  51. "maxIdle" value="30">  
  52. "maxWait" value="1000">  
  53. "poolPreparedStatements" value="true">  
  54. "defaultAutoCommit" value="false">  
  55.     </property></property></property></property></property></property></property></property></property></property></bean>  
  56.   
  57.     <!-- 数据源配置,使用应用服务器的数据库连接池 -->  
  58. "dataSource" jndi-name="java:comp/env/jdbc/ExampleDB">-->  
  59.   
  60.     <!-- Hibernate配置 -->  
  61. "sessionFactoryContent" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  62. "dataSource" ref="dataSourceContent">  
  63. "namingStrategy">  
  64.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  65.         </bean></property>  
  66. "hibernateProperties">  
  67.             <props>  
  68. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  69. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  70. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  71. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  72.                 </prop>  
  73. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  74.             </props>  
  75.         </property>  
  76. "packagesToScan" value="cn.puretext.entity.*">  
  77.     </property></property></bean>  
  78. "sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  79. "dataSource" ref="dataSourceIndex">  
  80. "namingStrategy">  
  81.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  82.         </bean></property>  
  83. "hibernateProperties">  
  84.             <props>  
  85. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  86. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  87. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  88. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  89.                 </prop>  
  90. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  91.             </props>  
  92.         </property>  
  93. "packagesToScan" value="cn.puretext.entity.*">  
  94.     </property></property></bean>  
  95.   
  96.     <!-- 事务管理器配置,单数据源事务 -->  
  97. "transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  98. "sessionFactory" ref="sessionFactoryContent">  
  99.     </property></bean>  
  100.   
  101.     <!-- 事务管理器配置,多数据源JTA事务-->  
  102. "transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager or  
  103.         WebLogicJtaTransactionManager">  
  104.     -->  
  105.   
  106.     <!-- 使用annotation定义事务 -->  
  107. "transactionManager">  
  108. </tx:annotation-driven><!--!----><!--!--<jee:jndi-lookup--></context:component-scan></beans>  


运行单元测试,报错,错误代码如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cn.puretext.unit.service.DaoTest': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private cn.puretext.dao.ArticleDao cn.puretext.unit.service.DaoTest.articleDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'articleDao': Autowiring of methods failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springside.modules.orm.hibernate.SimpleHibernateDao.setSessionFactory(org.hibernate.SessionFactory); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactoryContent, sessionFactoryIndex]

这和上面出现的错误是异曲同工的,只不过这次是ArticleDao类里面不知道注入哪一个SessionFactory,因此,需要修改ArticleDao类,重写setSessionFactory方法,并用@Resource注解指定,如下:


[java]  ​​view plain​​  ​​copy​​



  1. package cn.puretext.dao;  
  2.   
  3.   
  4. import javax.annotation.Resource;  
  5.   
  6. import org.hibernate.SessionFactory;  
  7. import org.springframework.stereotype.Repository;  
  8. import org.springside.modules.orm.hibernate.HibernateDao;  
  9.   
  10. import cn.puretext.entity.web.Article;  
  11.   
  12. @Repository  
  13. public class ArticleDao extends HibernateDao<article, long=""> {  
  14.   
  15. @Override  
  16. @Resource(name = "sessionFactoryContent")  
  17.     public void setSessionFactory(SessionFactory sessionFactory) {  
  18. // TODO Auto-generated method stub  
  19.         super.setSessionFactory(sessionFactory);  
  20.     }  
  21.   
  22. }  
  23. </article,>  


运行单元测试,成功。

第三步、配置多个TransactionManager,如下:


[java]  ​​view plain​​  ​​copy​​



  1. < xml version="1.0" encoding="UTF-8" >  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" default-lazy-init="true" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  3.   
  4.     <description>Spring公共配置文件 </description>  
  5.   
  6.     <!-- 定义受环境影响易变的变量 -->  
  7.     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  8. "systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">  
  9. "ignoreResourceNotFound" value="true">  
  10. "locations">  
  11.             <list>  
  12.                 <!-- 标准配置 -->  
  13.                 <value>classpath*:/application.properties</value>  
  14.                 <!-- 本地开发环境配置 -->  
  15.                 <value>classpath*:/application.local.properties</value>  
  16.                 <!-- 服务器生产环境配置 -->  
  17.                 <!---->file:/var/myapp/application.server.properties -->  
  18.             <!--!----></list>  
  19.         </property>  
  20.     </property></property></bean>  
  21.   
  22. @Required,@Autowired的属性被注入 -->  
  23.     <context:component-scan base-package="cn.puretext">  
  24.   
  25.     <!-- 数据源配置,使用应用内的DBCP数据库连接池 -->  
  26. "dataSourceContent" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  27.         <!-- Connection Info -->  
  28. "driverClassName" value="com.mysql.jdbc.Driver">  
  29. "url" value="${jdbc.urlContent}">  
  30. "username" value="${jdbc.username}">  
  31. "password" value="${jdbc.password}">  
  32.   
  33.         <!-- Connection Pooling Info -->  
  34. "initialSize" value="5">  
  35. "maxActive" value="100">  
  36. "maxIdle" value="30">  
  37. "maxWait" value="1000">  
  38. "poolPreparedStatements" value="true">  
  39. "defaultAutoCommit" value="false">  
  40.     </property></property></property></property></property></property></property></property></property></property></bean>  
  41. "dataSourceIndex" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  42.         <!-- Connection Info -->  
  43. "driverClassName" value="com.mysql.jdbc.Driver">  
  44. "url" value="${jdbc.urlIndex}">  
  45. "username" value="${jdbc.username}">  
  46. "password" value="${jdbc.password}">  
  47.   
  48.         <!-- Connection Pooling Info -->  
  49. "initialSize" value="5">  
  50. "maxActive" value="100">  
  51. "maxIdle" value="30">  
  52. "maxWait" value="1000">  
  53. "poolPreparedStatements" value="true">  
  54. "defaultAutoCommit" value="false">  
  55.     </property></property></property></property></property></property></property></property></property></property></bean>  
  56.   
  57.     <!-- 数据源配置,使用应用服务器的数据库连接池 -->  
  58. "dataSource" jndi-name="java:comp/env/jdbc/ExampleDB">-->  
  59.   
  60.     <!-- Hibernate配置 -->  
  61. "sessionFactoryContent" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  62. "dataSource" ref="dataSourceContent">  
  63. "namingStrategy">  
  64.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  65.         </bean></property>  
  66. "hibernateProperties">  
  67.             <props>  
  68. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  69. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  70. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  71. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  72.                 </prop>  
  73. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  74.             </props>  
  75.         </property>  
  76. "packagesToScan" value="cn.puretext.entity.*">  
  77.     </property></property></bean>  
  78. "sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  79. "dataSource" ref="dataSourceIndex">  
  80. "namingStrategy">  
  81.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  82.         </bean></property>  
  83. "hibernateProperties">  
  84.             <props>  
  85. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  86. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  87. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  88. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  89.                 </prop>  
  90. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  91.             </props>  
  92.         </property>  
  93. "packagesToScan" value="cn.puretext.entity.*">  
  94.     </property></property></bean>  
  95.   
  96.     <!-- 事务管理器配置,单数据源事务 -->  
  97. "transactionManagerContent" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  98. "sessionFactory" ref="sessionFactoryContent">  
  99.     </property></bean>  
  100. "transactionManagerIndex" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  101. "sessionFactory" ref="sessionFactoryIndex">  
  102.     </property></bean>  
  103.   
  104.     <!-- 事务管理器配置,多数据源JTA事务-->  
  105. "transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager or  
  106.         WebLogicJtaTransactionManager">  
  107.     -->  
  108.   
  109.     <!-- 使用annotation定义事务 -->  
  110. "transactionManagerContent">  
  111. </tx:annotation-driven><!--!----><!--!--<jee:jndi-lookup--></context:component-scan></beans>  
  112.   
  113. 这个时候运行还是会出错,出错的原因为 org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'transactionManager' is defined,因为该出错信息很短,我也难以找出究竟是哪个地方需要名为“transactionManager”的事务管理器 ,改个名字都不行,看来Spring的自动注入有时候也错综复杂害人不浅。不过,如果把上面的其中一个名字改成“transactionManger”, 另外一个名字不改,运行是成功的,如下:  
  114. <!-- 事务管理器配置,单数据源事务 -->  
  115. "transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  116. "sessionFactory" ref="sessionFactoryContent">  
  117.     </property></bean>  
  118. "transactionManagerIndex" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  119. "sessionFactory" ref="sessionFactoryIndex">  
  120.     </property></bean>  


这个时候得出结论是,可以配置多个TransactionManager,但是必须有一个的名字是transactionManager。

第四步、配置多个,如下:


[java]  ​​view plain​​  ​​copy​​



  1. <!-- 使用annotation定义事务 -->  
  2. "transactionManager">  
  3. "transactionManagerIndex">  
  4. </tx:annotation-driven></tx:annotation-driven>  


运行测试,天啦,竟然成功了。和我之前预料的完全不一样,居然在一个配置文件中配置多个一点 问题都没有。那么在使用@Transactional的地方,它真的能够选择正确的事务管理器吗?我不得不写更多的代码来进行测试。那就针对索引数据库中 的表写一个Entity,写一个Dao测试一下吧。

代码如下:


[java]  ​​view plain​​  ​​copy​​



  1. package cn.puretext.entity.web;  
  2.   
  3. import javax.persistence.Column;  
  4. import javax.persistence.Entity;  
  5. import javax.persistence.Table;  
  6.   
  7. import org.hibernate.annotations.Cache;  
  8. import org.hibernate.annotations.CacheConcurrencyStrategy;  
  9.   
  10. import cn.puretext.entity.IdEntity;  
  11.   
  12. @Entity  
  13. // 表名与类名不相同时重新定义表名.  
  14. @Table(name = "articles")  
  15. // 默认的缓存策略.  
  16. @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)  
  17. public class ArticleIndex extends IdEntity {  
  18.     private String subject;  
  19.     private String webServer;  
  20.   
  21.     public String getSubject() {  
  22.         return subject;  
  23.     }  
  24.   
  25.     public void setSubject(String subject) {  
  26.         this.subject = subject;  
  27.     }  
  28. @Column(name = "webserver")  
  29.     public String getWebServer() {  
  30.         return webServer;  
  31.     }  
  32.   
  33.     public void setWebServer(String webServer) {  
  34.         this.webServer = webServer;  
  35.     }  
  36. }  



[java]  ​​view plain​​  ​​copy​​



  1. package cn.puretext.dao;  
  2.   
  3. import javax.annotation.Resource;  
  4.   
  5. import org.hibernate.SessionFactory;  
  6. import org.springframework.stereotype.Repository;  
  7. import org.springside.modules.orm.hibernate.HibernateDao;  
  8.   
  9. import cn.puretext.entity.web.ArticleIndex;  
  10.   
  11. @Repository  
  12. public class ArticleIndexDao extends HibernateDao<articleindex, long=""> {  
  13. @Override  
  14. @Resource(name = "sessionFactoryIndex")  
  15.     public void setSessionFactory(SessionFactory sessionFactory) {  
  16. // TODO Auto-generated method stub  
  17.         super.setSessionFactory(sessionFactory);  
  18.     }  
  19. }</articleindex,>  



[java]  ​​view plain​​  ​​copy​​



  1. package cn.puretext.unit.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import javax.annotation.Resource;  
  6. import javax.sql.DataSource;  
  7.   
  8. import org.junit.Test;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.transaction.annotation.Transactional;  
  11. import org.springside.modules.orm.Page;  
  12. import org.springside.modules.test.junit4.SpringTxTestCase;  
  13.   
  14. import cn.puretext.dao.ArticleDao;  
  15. import cn.puretext.dao.ArticleIndexDao;  
  16. import cn.puretext.entity.web.Article;  
  17. import cn.puretext.entity.web.ArticleIndex;  
  18. import cn.puretext.service.ServiceException;  
  19.   
  20. public class DaoTest extends SpringTxTestCase {  
  21. @Autowired  
  22.     private ArticleDao articleDao;  
  23. @Autowired  
  24.     private ArticleIndexDao articleIndexDao;  
  25.       
  26.     public void setArticleIndexDao(ArticleIndexDao articleIndexDao) {  
  27.         this.articleIndexDao = articleIndexDao;  
  28.     }  
  29.   
  30.     public void setArticleDao(ArticleDao articleDao) {  
  31.         this.articleDao = articleDao;  
  32.     }  
  33.   
  34. @Override  
  35. @Resource(name = "dataSourceContent")  
  36.     public void setDataSource(DataSource dataSource) {  
  37. // TODO Auto-generated method stub  
  38.         super.setDataSource(dataSource);  
  39.     }  
  40.   
  41. @Test  
  42. @Transactional  
  43.     public void addArticle() {  
  44.         Article article = new Article();  
  45. "article test");  
  46. "article test");  
  47.         articleDao.save(article);  
  48.     }  
  49.   
  50. @Test  
  51. @Transactional  
  52.     public void pageQuery() {  
  53.         Page<article> page = new Page<article>();  
  54. 10);  
  55. 2);  
  56.         page = articleDao.getAll(page);  
  57.         List<article> articles = page.getResult();  
  58.     }  
  59.       
  60. @Test  
  61. @Transactional  
  62.     public void addIndex() {  
  63.         ArticleIndex articleIndex = new ArticleIndex();  
  64. "test");  
  65. "www001");  
  66.         articleIndexDao.save(articleIndex);  
  67.     }  
  68.       
  69. @Test  
  70. @Transactional  
  71.     public void addArticleAndAddIndex() {  
  72.         addArticle();  
  73.         addIndex();  
  74.         throw new ServiceException("测试事务回滚");  
  75.     }  
  76. }  
  77. </article></article></article>  


运行测试,结果还是成功的。到目前,发现在一个项目中使用多个TransactionManager可以正常运行,但是有两个问题需要考虑:
1、为什么必须得有一个TransactionManager名字为transactionManager?
2、这两个TransactionManager真的能正常工作吗?
3、OpenSessionInView的问题怎么解决?

以上的三个问题在单元测试中是不能找出答案的,我只好再去写Action层的代码,期望能够从中得到线索。经过一天艰苦的努力,终于真相大白:
1、并不是必须有一个TransactionManager的名字为transactionMananger,这只是单元测试在搞鬼,在真实的Web环境 中,无论两个TransactionManager取什么名字都可以,运行不会报错。所以这个答案很明确,是因为单元测试的基类需要一个名为 transactionMananger的事务管理器。
2、在单元测试中,只能测试Dao类和Entity类能否正常工作,但是由于单元测试结束后事务会自动回滚,不会把数据写入到数据库中,所以没有办法确定 两个TransactionManager能否正常工作。在真实的Web环境中,问题很快就浮出水面,只有一个数据库中有数据,另外一个数据库中没有,经 过调整的位置并对比分析,发现只有放在前面的TransactionMananger的事务 能够正常提交,放在后面的TransactionManager的事务不能提交,所以永远只有一个数据库里面有数据。
3、如果早一点脱离单元测试而进入真实的Web环境,就会早一点发现OpenSessionInViewFilter的问题,因为只要配置多个 SessionFactory,运行的时候OpenSessionInViewFilter就会报错。为了解决这个问题,我只能去阅读 OpenSessionInViewFilter的源代码,发现它在将Session绑定到线程的时候用的是Map,而且使用 SessionFactory作为Map的key,这就说明在线程中绑定多个Session不会冲突,也进一步说明可以在web.xml中配置多个 OpenSessionInViewFilter。而我也正是通过配置多个OpenSessionInViewFilter来解决问题的。我的 web.xml文件如下:


[java]  ​​view plain​​  ​​copy​​



  1. < xml version="1.0" encoding="UTF-8" >  
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  3.   
  4.     <display-name>PureText</display-name>  
  5.     <!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔  
  6.         此参数用于后面的Spring Context Loader -->  
  7.     <context-param>  
  8.         <param-name>contextConfigLocation</param-name>  
  9.         <param-value>classpath*:/applicationContext*.xml</param-value>  
  10.     </context-param>  
  11.   
  12.     <!-- Character Encoding filter -->  
  13.     <filter>  
  14.         <filter-name>encodingFilter</filter-name>  
  15.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
  16.         <init-param>  
  17.             <param-name>encoding</param-name>  
  18. 8</param-value>  
  19.         </init-param>  
  20.         <init-param>  
  21.             <param-name>forceEncoding</param-name>  
  22.             <param-value>true</param-value>  
  23.         </init-param>  
  24.     </filter>  
  25.   
  26.     <filter>  
  27.         <filter-name>hibernateOpenSessionInViewFilterContent</filter-name>  
  28.         <filter-class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter</filter-class>  
  29.         <init-param>  
  30.             <param-name>excludeSuffixs</param-name>  
  31.             <param-value>js,css,jpg,gif</param-value>  
  32.         </init-param>  
  33.         <init-param>        
  34.                <param-name>sessionFactoryBeanName</param-name>  
  35.             <param-value>sessionFactoryContent</param-value>     
  36.         </init-param>      
  37.     </filter>  
  38.     <filter>  
  39.         <filter-name>hibernateOpenSessionInViewFilterIndex</filter-name>  
  40.         <filter-class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter</filter-class>  
  41.         <init-param>  
  42.             <param-name>excludeSuffixs</param-name>  
  43.             <param-value>js,css,jpg,gif</param-value>  
  44.         </init-param>  
  45.         <init-param>        
  46.                <param-name>sessionFactoryBeanName</param-name>  
  47.             <param-value>sessionFactoryIndex</param-value>     
  48.         </init-param>      
  49.     </filter>  
  50.     <!-- SpringSecurity filter-->  
  51.     <filter>  
  52.         <filter-name>springSecurityFilterChain</filter-name>  
  53.         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  54.     </filter>  
  55.   
  56.     <!-- Struts2 filter -->  
  57.     <filter>  
  58.         <filter-name>struts2Filter</filter-name>  
  59.         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  60.     </filter>  
  61.   
  62.     <filter-mapping>  
  63.         <filter-name>encodingFilter</filter-name>  
  64.         <url-pattern>/*</url-pattern>  
  65.     </filter-mapping>  
  66.   
  67.   
  68.     <filter-mapping>  
  69.         <filter-name>springSecurityFilterChain</filter-name>  
  70.         <url-pattern>/*</url-pattern>  
  71.     </filter-mapping>  
  72.     <filter-mapping>  
  73.         <filter-name>hibernateOpenSessionInViewFilterContent</filter-name>  
  74.         <url-pattern>/*</url-pattern>  
  75.     </filter-mapping>  
  76.     <filter-mapping>  
  77.         <filter-name>hibernateOpenSessionInViewFilterIndex</filter-name>  
  78.         <url-pattern>/*</url-pattern>  
  79.     </filter-mapping>  
  80.     <filter-mapping>  
  81.         <filter-name>struts2Filter</filter-name>  
  82.         <url-pattern>/*</url-pattern>  
  83.     </filter-mapping>  
  84.   
  85.     <!--Spring的ApplicationContext 载入 -->  
  86.     <listener>  
  87.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  88.     </listener>  
  89.   
  90.     <!-- Spring 刷新Introspector防止内存泄露 -->  
  91.     <listener>  
  92.         <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  
  93.     </listener>  
  94.   
  95.     <!-- session超时定义,单位为分钟 -->  
  96.     <session-config>  
  97. 20</session-timeout>  
  98.     </session-config>  
  99.   
  100.     <!-- 出错页面定义 -->  
  101.     <error-page>  
  102.         <exception-type>java.lang.Throwable</exception-type>  
  103. 500.jsp</location>  
  104.     </error-page>  
  105.     <error-page>  
  106. 500</error-code>  
  107. 500.jsp</location>  
  108.     </error-page>  
  109.     <error-page>  
  110. 404</error-code>  
  111. 404.jsp</location>  
  112.     </error-page>  
  113.     <error-page>  
  114. 403</error-code>  
  115. 403.jsp</location>  
  116.     </error-page>  
  117. </web-app>  


经过上面的分析,发现使用多个TransactionManager是不可行的(这个时候我在想,也许不使用Annotation就可以使用多个 TransactionMananger吧,毕竟Spring的AOP应该是可以把不同的TransactionManager插入到不同的类和方法中, 但是谁愿意走回头路呢?毕竟都已经是@Transactional的年代了),虽然运行不会报错,但是只有一个TransactionManager的事 务能够正常提交。所以测试进入下一步:

第五步、使用JTATransactionManager

简单地修改配置文件,使用JTATransactionManager做为事务管理器,配置文件我就不列出来了,运行,结果抱错,错误信息如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainProxy': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainList': Cannot create inner bean '(inner bean)' of type [org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator] while setting bean property 'filters' with key [10]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'filterSecurityInterceptor' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'filterSecurityInterceptor' defined in file [D:Temp1-PureTextWEB-INFclassesapplicationContext-security.xml]: Cannot resolve reference to bean 'databaseDefinitionSource' while setting bean property 'objectDefinitionSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'databaseDefinitionSource': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionInterceptor#0': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in file [D:Temp1-PureTextWEB-INFclassesapplicationContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No JTA UserTransaction available - specify either 'userTransaction' or 'userTransactionName' or 'transactionManager' or 'transactionManagerName'

通过分析,发现其中最关键的一句是No JTA UserTransaction available,看来,我们只能进入到第六步,使用GlassFish了。

第六步、将项目部署到GlassFish中

将项目简单地部署到GlassFish中之后,项目可以成功运行,没有报错,说明JTA UserTransaction问题解决了,但是检查数据库却发现依然没有数据,看来JTATransactionManager不仅要和应用服务器配合 使用,还要和JNDI数据源一起使用。将数据源的配置修改为JNDI后,问题解决。下面是我的配置文件:


[java]  ​​view plain​​  ​​copy​​



  1. < xml version="1.0" encoding="UTF-8" >  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" default-lazy-init="true" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  3.   
  4.     <description>Spring公共配置文件 </description>  
  5.   
  6.     <!-- 定义受环境影响易变的变量 -->  
  7.     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  8. "systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">  
  9. "ignoreResourceNotFound" value="true">  
  10. "locations">  
  11.             <list>  
  12.                 <!-- 标准配置 -->  
  13.                 <value>classpath*:/application.properties</value>  
  14.                 <!-- 本地开发环境配置 -->  
  15.                 <value>classpath*:/application.local.properties</value>  
  16.                 <!-- 服务器生产环境配置 -->  
  17.                 <!---->file:/var/myapp/application.server.properties -->  
  18.             <!--!----></list>  
  19.         </property>  
  20.     </property></property></bean>  
  21.   
  22. @Required,@Autowired的属性被注入 -->  
  23.     <context:component-scan base-package="cn.puretext">  
  24.   
  25.     <!-- 数据源配置,使用应用服务器的数据库连接池 -->  
  26. "dataSourceContent" jndi-name="jdbc/dataSourceContent">  
  27. "dataSourceIndex" jndi-name="jdbc/dataSourceIndex">  
  28.   
  29.     <!-- Hibernate配置 -->  
  30. "sessionFactoryContent" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  31. "dataSource" ref="dataSourceContent">  
  32. "namingStrategy">  
  33.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  34.         </bean></property>  
  35. "hibernateProperties">  
  36.             <props>  
  37. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  38. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  39. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  40. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  41.                 </prop>  
  42. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  43.             </props>  
  44.         </property>  
  45. "packagesToScan" value="cn.puretext.entity.*">  
  46.     </property></property></bean>  
  47. "sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  48. "dataSource" ref="dataSourceIndex">  
  49. "namingStrategy">  
  50.             <bean class="org.hibernate.cfg.ImprovedNamingStrategy">  
  51.         </bean></property>  
  52. "hibernateProperties">  
  53.             <props>  
  54. "hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
  55. "hibernate.show_sql">${hibernate.show_sql}</prop>  
  56. "hibernate.format_sql">${hibernate.format_sql}</prop>  
  57. "hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider  
  58.                 </prop>  
  59. "hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>  
  60.             </props>  
  61.         </property>  
  62. "packagesToScan" value="cn.puretext.entity.*">  
  63.     </property></property></bean>  
  64.   
  65.     <!-- 事务管理器配置,单数据源事务 -->  
  66. "transactionManagerContent" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  67. "sessionFactory" ref="sessionFactoryContent">  
  68.       
  69. "transactionManagerIndex" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  70. "sessionFactory" ref="sessionFactoryIndex">  
  71.     </property></bean>  
  72.     -->  
  73.       
  74.     <!-- 事务管理器配置,多数据源JTA事务-->  
  75.       
  76. "transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
  77.       
  78.   
  79.     <!-- 使用annotation定义事务 -->  
  80. "transactionManager">  
  81.       
  82. </tx:annotation-driven></bean><!--!----></jee:jndi-lookup></jee:jndi-lookup></context:component-scan></beans>  


最后,我得出的结论是:要想使用多个数据库,就必须使用JTATransactionMananger,必须使用GlassFish等应用服务器而不是Tomcat,必须使用JNDI来管理dataSource。

如果一定要使用Tomcat呢?

这确实是一个难题,但是并不代表着没有解决办法。经过广泛的Google一番之后,终于发现了一个好东东,那就是JOTM,它的全称就是Java Open Transaction Mananger,它的作用就是可以单独提供JTA事务管理的功能,不需要应用服务器。JOTM的使用方法有两种,一种就是把它配置到项目中,和 Spring结合起来使用,另外一种就是把它配置到Tomcat中,这时,Tomcat摇身一变就成了和GlassFish一样的能够提供JTA功能的服 务器了。

JOTM的官方网站为http://jotm.ow2.org,这是它的新网站,旧网站为http://jotm.objectweb.org。

我选择了把JOTM 2.0.11整合到Tomcat中的方法进行了测试,结果发现还是不能够正常运行,我使用的是JOTM2.0.11,Tomcat 6.0.20,JKD 6 Update10。看来还得继续折腾下去了。

另外一个开源的JTA事务管理器是Atomikos,它供了事务管理和连接池,不需要应用服务器支持,其官方网站为http://www.atomikos.com/。有兴趣的朋友可以试试。

标签:事务,hibernate,数据源,springframework,value,Spring,org,import,class
From: https://blog.51cto.com/xichenguan/5976203

相关文章

  • SpringBoot系列之数据库初始化-datasource配置方式
    【DB系列】数据库初始化-datasource配置方式|一灰灰Blog在我们的日常业务开发过程中,如果有db的相关操作,通常我们是直接建立好对应的库表结构,并初始化对应的数据,即更......
  • Spring boot 的路径踩坑
     代码@ApiOperation(value="测试")@PostMapping("/GetFileSystem")publicList<String>getFileSystem(HttpServletRequestrequest){List<S......
  • Spring Cloud 使用 Resilience4j 实现服务熔断
    CircuitBreaker断路器服务熔断是为了保护我们的服务,比如当某个服务出现问题的时候,控制打向它的流量,让它有时间去恢复,或者限制一段时间只能有固定数量的请求打向这个服务......
  • springboot整合Jackson
    springboot整合JacksonJackson简介Jackson是一套适合java的数据处理工具,用于JSON格式数据的解析与生成,支持多种类型,是SpringMVC内置解析器。除了Jackson,常用的JSON解......
  • SpringBoot高级篇搜索之Solr环境搭建与简单测试
    搜索可以说是非常常见的场景了,一般选择比较多的有solr和es,底层都是基于Lucene搜索引擎实现。之前简单的使用过solr,一直没有成体系的学习过,正好需要给一个内部项目封装统一的......
  • 基于Seata探寻分布式事务的实现方案
    作者:京东物流技术与数据智能部张硕1背景知识随着业务的快速发展、业务复杂度越来越高,几乎每个公司的系统都会从单体走向分布式,特别是转向微服务架构。随之而来就必然遇......
  • 使用 Spring Boot 快速构建 Spring 框架应用,PropertyPlaceholderConfigurer
    Spring框架对于很多Java开发人员来说都不陌生。自从2002年发布以来,Spring框架已经成为企业应用开发领域非常流行的基础框架。有大量的企业应用基于Spring框架来开发......
  • Manage Spring Boot Logs with Elasticsearch, Logstash and Kibana
    下载地址:https://www.elastic.co/downloads Whentimecomestodeployanewproject,oneoftenoverlookedaspectislogmanagement.ELKstack(Elasticsearch,Logs......
  • spring-boot 整合redis作为数据缓存
     添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-redis</artifactId></dependency>......
  • org.springframework.web.bind.ServletRequestDataBinde
    org.springframework.validationClassDataBinder​​java.lang.Object​​org.springframework.validation.DataBinderAllImplementedInterfaces:​​PropertyEditorRe......