spring4.1+mybatis3.5实践总结

实践目的是利用spring的事务管理代替mybatis的事务管理,而且是从http请求层面开启事务,保证在一个请求线程中完成事务的一致性。
将两者结合起来的是另外一个开源包mybatis-spring,这次实践使用的是2.0的版本。
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.0</version>
</dependency>


一、spring的设置 (完整配置,部分片段后面会有单独描述)
<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">

<context:component-scan base-package="com.xxxx.app" />

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>

<!-- 注解配置 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<context:annotation-config />

<!-- 数据库连接池,这里使用alibaba的Druid -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=familydb" />
<property name="username" value="sa" />
<property name="password" value="123456" />
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxxx.app.mapper" />
</bean>


</beans>
几点说明:
1、使用druid数据库连接池
2、使用SqlSessionFactoryBean代替SqlSessionFactoryBuilder来构建SqlSession工厂
3、使用DataSourceTransactionManager 作为事务管理器
4、使用注解的方式开启事务(后面有描述)
5、使用MapperScannerConfigurer 自动创建MapperFactoryBean,以减少配置信息(后面有描述)


二、使用 mapper 接口替换DAO层代码
为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象 (DAO)的代码,MyBatis-Spring 提供了一个动态代理的实现:MapperFactoryBean。这个类 可以让你直接注入数据映射器接口到你的 service 层 bean 中。当使用映射器时,你仅仅如调 用你的 DAO 一样调用它们就可以了,但是你不需要编写任何 DAO 实现的代码,因为 MyBatis-Spring 将会为你创建代理。
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.xxxx.app.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程序中。
这样做,可以使用mapper接口直接替换DAO层代码,但需要有如下要求:
1、mapper接口和mapper配置文件必须放在同一个目录
2、mapper接口和mapper配置文件必须必须使用相同的文件名,如:UserMapper.class UserMapper.xml
3、mapper配置文件中的命名空间必须使用mapper接口的长限定名,如:com.xxxx.app.mapper.UserMapper

为了不在 Spring 的 XML 配置文件中注册所有的映射器,可以改用 MapperScannerConfigurer , 它 将 会 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxxx.app.mapper" />
</bean>
mapper接口代码如下(为了简化,使用一个mapper接口操作两个表,这种做法是不推荐的,这里只是测试):
public interface UserMapper {
@Insert("insert tmp_class(class_name,class_teacher) values('木渎班',#{teacher, jdbcType=VARCHAR})")
void addClass(String teacher);

@Insert("insert tmp_course(course_name,course_teacher) values('颜色与革命','张老师')")
void addCourse();
}
待插入数据的数据库表创建语句如下(这里使用的是sqlserver2016 express):
create table tmp_class(
class_id int not null identity(1,1),
class_name nvarchar(20) not null,
class_teacher nvarchar(20) not null,
PRIMARY KEY (class_id)
)
create table tmp_course(
course_id int not null identity(1,1),
course_name nvarchar(20) not null,
course_teacher nvarchar(20) not null,
PRIMARY KEY (course_id)
)


三、在service层的实现类中使用 @Autowired 注解获取mapper实例(其实是MapperFactoryBean 创建的代理类实例)
@Service
public class CourseManagerImpl implements CourseManager {
@Autowired
private UserMapper userMapper;

public void addCourse() {
userMapper.addCourse();
}
}


四、在controller层使用 @Transactional 注解启动事务()
这个注解用于开启事务管理,注意 @Transactional 注解的使用前提是该方法所在的类是一个Spring Bean,所以在方法加了 @Transactional注解,就需要给类加 @Service、 @Repository、 @Controller、 @Component 四个注解其中之一将类声明为一个Spring的Bean。

@Controller
@RequestMapping("/teaching-module")
public class TeachingController {

@Autowired
ClassManager classMgr;

@Autowired
CourseManager courseMgr;

@Transactional
@RequestMapping(value = "/addTeaching", method = RequestMethod.POST)
@ResponseBody
public String addTeaching(@RequestParam("classTeacher") String teacher){
courseMgr.addCourse();
classMgr.addClass(teacher);
return "successed";
}
}

使用 @Autowired 注解获取两个server实例(这两个service层的实现类必须加上 @Service注解),分别调用其方法对两个表添加数据,保证只有两个表的数据插入都正确时才能同一提交事务。


五、测试的HTML代码
<form name="serForm" action="../teaching-module/addTeaching" method="post" >
Class Teacher: <input type="text" name="classTeacher" value="lilaoshi"/>
<input type="submit" value="add teaching task"/>
</form>
通过输入的文字长度(测试字段要求20个文字长度)来控制插入是否成功,从而可以验证两个表是否插入数据。

猜你喜欢

转载自www.cnblogs.com/ylft/p/10564003.html