spring是有多个配置文件的,分类:1.按功能分组,2.按模块分+公共的
1.执行:在src下创建springxml类型的main.xml
当mybatis集成spring之后,我们之前写的mybatisUtils类就可以被代替了。
由于我们需要工厂创建机制:SqlSession->依赖于SqlSessionFactory->1.数据连接,2.映射文件和接口
2.此时映射文件和接口是现成的,只需加载即可。数据库连接可通过commons-dbcp-1.4.jar进行解决,提供了一个开源的DataSource(记不住可以直接看jar包)
开始配置:
配置main.xml,连接数据库。
<!--数据源:Spring管理的数据源、web容器管理的数据源-->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/news?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="initialSize" value="2"/><!---连接数,初始的时候有几个连接池,连接数-->
<property name="maxActive" value="10"/><!---最大连接数-->
<property name="minIdle" value="2"/><!---最小空闲数, 空闲连接,-->
</bean>
之后进行SqlSessionFactory的配置(将mybatis中的mybatisUtil交给spring进行工作)(本次的作用为:1.连接数据库,2.扫描映射文件)
<!--创建工厂机制SqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:com/dao/*.xml"/>
</bean>
spring自动生成Mapper实现类的bean,是dao层里xml文件里类的首字母小写。
<!--Spring自动生成Mapper实现类的bean,相当于获取Mapper类的配置的bean-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dao"/><!--扫描包,即扫描Dao包-->
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
</bean>
单元测试:表示可以获取类的bean:
package com.dao; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class NewsMapperTest { static ApplicationContext ctx = null; @BeforeClass public static void load(){ ctx = new ClassPathXmlApplicationContext("main.xml"); } @Test public void mapper(){ NewsMapper newsMapper = (NewsMapper)ctx.getBean("newsMapper"); Assert.assertNotNull(newsMapper); } }
1、共同语言,程序员<=客户语言、词汇、业务=>客户
2、使用多个Mapper对象操作数据库
3、事务、日志、异常、安全都位于业务层
NewsMapper->NewsService->NewsController->页面
业务类使用接口,目的是解决spring中代理模式的问题。
eg:接口
package com.service; import com.bean.News; import java.util.List; import java.util.Map; /** * 1、共同语言,程序员<=客户语言、词汇、业务=>客户 * 2、使用多个Mapper对象操作数据库 * 3、事务、日志、异常、安全都位于业务层 * NewsMapper->NewsService->NewsController->页面 */ public interface NewsService { void publish(News news); void edit(News news); void approve(News news); News get(int id); News get(Map<String, Object> params); List<News> list(Map<String, Object> params); }
实现:
package com.service.impl; import com.bean.News; import com.dao.NewsMapper; import com.dao.UsersMapper; import com.service.NewsService; import java.util.List; import java.util.Map; public class NewsServiceImpl implements NewsService { private NewsMapper newsMapper; @Override public void publish(News news) { news.setPubtime(new java.util.Date()); news.setState(1); // 新建新闻 news.setIsElite(0); // 非精华帖 newsMapper.add(news); } @Override public void edit(News news) { newsMapper.update(news); } @Override public void approve(News news) { } @Override public News get(int id) { return newsMapper.findNewsWithReplys(id); } @Override public News get(Map<String, Object> params) { return newsMapper.findNewsByParams(params); } @Override public List<News> list(Map<String, Object> params) { return newsMapper.find(params); } public NewsMapper getNewsMapper() { return newsMapper; } public void setNewsMapper(NewsMapper newsMapper) { this.newsMapper = newsMapper; } }
问题:在我们写了add方法操作后,并没有进行commit操作。我们执行add方法(方法带有事务)操作仍然会成功添加,此时并不是我们想要的,于是我们需要管理事务。
方法:采用AOP的方式实现。
问题:在业务层,在两个相近的两个数据库操作,并不是只打开一次数据库,而是两次。
配置步骤:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
<!--导入事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务的规则--> <tx:advice id="transAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" read-only="true"/> <!--拒绝所有,所有只读--> <tx:method name="publish" propagation="REQUIRED"/> <tx:method name="edit" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
配置事务的规则:那些方法上如何运用事务:1.白名单机制:拒绝所有,允许个别。2.黑名单机制:允许所有,拒绝个别。属性:propagation(传播属性):requried表示必须要。support(表示支持事务,常需要两个事务配合)。isolation(隔离性):read_committed(绝大多数需要的)
<!--编织-->
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/>
</aop:config>
在com.service子包下的类进行事务增强,增强的是transAdvice.
问题:白名单控制在业务层,那么如果有人直接访问Dao层如何处理?
问题:在dao层依旧可能会出现挨着的两个事务会出现打开两次数据库的问题。
即直接通过newsMapper进行数据库的操作。
解决方法:类似于业务层:
第一步与第二步与上一个相同:
第三步:通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则。
<tx:advice id="daoAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice>
第四步:编织,使切入点与事务规则进行配置。
<!--编织-->
<aop:config>
<aop:pointcut id="servicePointcut"
expression="execution(* com.service..*.*(..))"/>
<aop:pointcut id="daoPointvut" expression="execution(* com.dao..*.*(..))"/>
<aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/>
<aop:advisor advice-ref="daoAdvice" pointcut-ref="daoPointvut"/>
</aop:config>
结果:此时dao层则会不再能进行添加等数据库操作。
总结:目前以上操作:在业务层可以进行数据库操作业务处理,而无法直接通过dao层进行处理。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!--数据源:Spring管理的数据源、web容器管理的数据源--> <bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/news?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> <property name="initialSize" value="2"/><!---连接数,初始的时候有几个连接池,连接数--> <property name="maxActive" value="10"/><!---最大连接数--> <property name="minIdle" value="2"/><!---最小空闲数, 空闲连接,--> </bean> <!--创建工厂机制SqlSessionFactory--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:com/dao/*.xml"/> </bean> <!--Spring自动生成Mapper实现类的bean,相当于获取Mapper类的配置的bean--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.dao"/><!--扫描包,即扫描Dao包--> <property name="sqlSessionFactoryBeanName" value="sessionFactory"/> </bean> <bean class="com.service.impl.NewsServiceImpl" id="newsService"> <property name="newsMapper" ref="newsMapper"/> </bean> <!--导入事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--配置事务的规则:那些方法上如何运用事务--> <tx:advice id="transAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" read-only="true"/> <tx:method name="publish" propagation="REQUIRED"/> <tx:method name="edit" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <tx:advice id="daoAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!--编织--> <aop:config> <aop:pointcut id="servicePointcut" expression="execution(* com.service..*.*(..))"/> <aop:pointcut id="daoPointvut" expression="execution(* com.dao..*.*(..))"/> <aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/> <aop:advisor advice-ref="daoAdvice" pointcut-ref="daoPointvut"/> </aop:config> </beans>
对于上面关于dao层直接处理数据库的操作问题,不建议这样,已注解掉。关于这个问题,是可以通过管理手段来解决这个问题。
(10).spring与mybatis的集成 业务层的必须性
原文:https://www.cnblogs.com/zxdup/p/13122261.html