
两种方案
方案1:当只有读 *** 作的时候,直接 *** 作读库(从库);
当在写事务(即写主库)中读时,也是读主库(即参与到主库 *** 作),这样的优势是可以防止写完后可能读不到刚才写的数据;
此方案其实是使用事务传播行为为:SUPPORTS解决的。
方案2:当只有读 *** 作的时候,直接 *** 作读库(从库);
当在写事务(即写主库)中读时,强制走从库,即先暂停写事务,开启读(读从库),然后恢复写事务。
此方案其实是使用事务传播行为为:NOT_SUPPORTS解决的。
核心组件
cnjavasscommondatasourceReadWriteDataSource:读写分离的动态数据源,类似于AbstractRoutingDataSource,具体参考javadoc;
cnjavasscommondatasourceReadWriteDataSourceDecision:读写库选择的决策者,具体参考javadoc;
cnjavasscommondatasourceReadWriteDataSourceProcessor:此类实现了两个职责(为了减少类的数量将两个功能合并到一起了):读/写动态数据库选择处理器、通过AOP切面实现读/写选择,具体参考javadoc。
具体配置
1、数据源配置
11、写库配置
Java代码
<bean id="writeDataSource" class="orglogicalcobwebsproxoolProxoolDataSource">
<property name="alias" value="writeDataSource"/>
<property name="driver" value="${writeconnectiondriver_class}" />
<property name="driverUrl" value="${writeconnectionurl}" />
<property name="user" value="${writeconnectionusername}" />
<property name="password" value="${writeconnectionpassword}" />
<property name="maximumConnectionCount" value="${writeproxoolmaximumconnectioncount}"/>
<property name="minimumConnectionCount" value="${writeproxoolminimumconnectioncount}" />
<property name="statistics" value="${writeproxoolstatistics}" />
<property name="simultaneousBuildThrottle" value="${writeproxoolsimultaneousbuildthrottle}"/>
</bean>
12、读库配置
Java代码
<bean id="readDataSource1" class="orglogicalcobwebsproxoolProxoolDataSource">
<property name="alias" value="readDataSource"/>
<property name="driver" value="${readconnectiondriver_class}" />
<property name="driverUrl" value="${readconnectionurl}" />
<property name="user" value="${readconnectionusername}" />
<property name="password" value="${readconnectionpassword}" />
<property name="maximumConnectionCount" value="${readproxoolmaximumconnectioncount}"/>
<property name="minimumConnectionCount" value="${readproxoolminimumconnectioncount}" />
<property name="statistics" value="${readproxoolstatistics}" />
<property name="simultaneousBuildThrottle" value="${readproxoolsimultaneousbuildthrottle}"/>
</bean>
13、读写动态库配置
通过writeDataSource指定写库,通过readDataSourceMap指定从库列表,从库列表默认通过顺序轮询来使用读库,具体参考javadoc;
Java代码
<bean id="readWriteDataSource" class="cnjavasscommondatasourceReadWriteDataSource">
<property name="writeDataSource" ref="writeDataSource"/>
<property name="readDataSourceMap">
<map>
<entry key="readDataSource1" value-ref="readDataSource1"/>
<entry key="readDataSource2" value-ref="readDataSource1"/>
<entry key="readDataSource3" value-ref="readDataSource1"/>
<entry key="readDataSource4" value-ref="readDataSource1"/>
</map>
</property>
</bean>
2、XML事务属性配置
所以读方法必须是read-only(必须,以此来判断是否是读方法)。
Java代码
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save" propagation="REQUIRED" />
<tx:method name="add" propagation="REQUIRED" />
<tx:method name="create" propagation="REQUIRED" />
<tx:method name="insert" propagation="REQUIRED" />
<tx:method name="update" propagation="REQUIRED" />
<tx:method name="merge" propagation="REQUIRED" />
<tx:method name="del" propagation="REQUIRED" />
<tx:method name="remove" propagation="REQUIRED" />
<tx:method name="put" read-only="true"/>
<tx:method name="query" read-only="true"/>
<tx:method name="use" read-only="true"/>
<tx:method name="get" read-only="true" />
<tx:method name="count" read-only="true" />
<tx:method name="find" read-only="true" />
<tx:method name="list" read-only="true" />
<tx:method name="" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
3、事务管理器
事务管理器管理的是readWriteDataSource
Java代码
<bean id="txManager" class="orgspringframeworkjdbcdatasourceDataSourceTransactionManager">
<property name="dataSource" ref="readWriteDataSource"/>
</bean>
4、读/写动态数据库选择处理器
根据之前的txAdvice配置的事务属性决定是读/写,具体参考javadoc;
forceChoiceReadWhenWrite:用于确定在如果目前是写(即开启了事务),下一步如果是读,是直接参与到写库进行读,还是强制从读库读,具体参考javadoc;
Java代码
<bean id="readWriteDataSourceTransactionProcessor" class="cnjavasscommondatasourceReadWriteDataSourceProcessor">
<property name="forceChoiceReadWhenWrite" value="false"/>
</bean>
5、事务切面和读/写库选择切面
Java代码
<aop:config expose-proxy="true">
<!-- 只对业务逻辑层实施事务 -->
<aop:pointcut id="txPointcut" expression="execution( cnjavassservice())" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
<!-- 通过AOP切面实现读/写库选择 -->
<aop:aspect order="-2147483648" ref="readWriteDataSourceTransactionProcessor">
<aop:around pointcut-ref="txPointcut" method="determineReadOrWriteDB"/>
</aop:aspect>
</aop:config>
1、事务切面一般横切业务逻辑层;
2、此处我们使用readWriteDataSourceTransactionProcessor的通过AOP切面实现读/写库选择功能,order=IntegerMIN_VALUE(即最高的优先级),从而保证在 *** 作事务之前已经决定了使用读/写库。
6、测试用例
只要配置好事务属性(通过read-only=true指定读方法)即可,其他选择读/写库的 *** 作都交给readWriteDataSourceTransactionProcessor完成。
可以参考附件的:
cnjavassreadwriteReadWriteDBTestWithForceChoiceReadOnWriteFalse
cnjavassreadwriteReadWriteDBTestWithNoForceChoiceReadOnWriteTrue
可以下载附件的代码进行测试,具体选择主/从可以参考日志输出。
本质上其实是同一个概念,spring的事务是对数据库的事务的封装,最后本质的实现还是在数据库,假如数据库不支持事务的话,spring的事务是没有作用的数据库的事务说简单就只有开启,回滚和关闭,spring对数据库事务的包装,原理就是拿一个数据连接,根据spring的事务配置, *** 作这个数据连接对数据库进行事务开启,回滚或关闭 *** 作但是spring除了实现这些,还配合spring的传播行为对事务进行了更广泛的管理其实这里还有个重要的点,那就是事务中涉及的隔离级别,以及spring如何对数据库的隔离级别进行封装事务与隔离级别放在一起理解会更好些以上回答希望能帮助到你
首先,不要在数据库里直接存照片,那样太麻烦了,也占用空间。
数据库里只存一个照片文件的名称。
比如,数据库字段名为photo_name,则数据库内的数据为
photo_name
-----------------------
jpg
jpg
jpg
jpg等都是文件名。文件本身则在服务器上另找地方存储,比如存在img/photo目录下。
这样作了之后,在JSP页面上采用就可以直接显示了
<img src="img/photo/${userphotoName}" />
${userphotoName}是你从数据库中取出的照片文件名。
Spring测试框架提供MockMvc对象,可以在不需要客户端-服务端请求的情况下进行MVC测试,完全在服务端这边就可以执行Controller的请求,跟启动了测试服务器一样。
测试开始之前需要建立测试环境,setup方法被@Before修饰。通过工具,使用对象作为参数,创建一个MockMvc对象。
1、控制器层直接将list类型的数据存储到动态类上
2、视图层直接取出动态类存放到变量上,使用foreach循环遍历
例如:
model:
public class user{
public int uid{set;get;}
public string uname{set;get;}
}
controller:
user u = new user();
List<user> ulist = new List<user>();//定义list对象
for(i=0; i< 3; i++){
uuid = i;
uuname = "xxx"+i;
ulistadd(u);
}
var ViewBaguser = ulist;
view:
var ulist = ViewBaguser as List<user>;//赋值变量,指定类型
<select name="s1" class="s1">
foreach(var item in ulist){
<option value="@itemuid">@itemuname</option>
}
</select>
分享
springboot怎么从父框架查sql?SpringBoot框架篇12使用druid的monitor工具查看sql执行性能 2045阅读·0评论·2点赞2020所以springboot怎么从父框架查sql
以上就是关于如何在应用层通过spring特性解决数据库读写分离全部的内容,包括:如何在应用层通过spring特性解决数据库读写分离、spring的事务是用的数据库的事务吗、能不能把 springmvc mybatis查询数据库二进制照片显示到jsp 的代码给我看看。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)