后端这块最后还需要处理的就是事务了。
UserDao接口先加一个插入方法:
package mybatistest.dao;
import mybatistest.entity.User;
public interface UserDao extends BaseDao<User>{
public String insertUser(User user);
public String getUserString(String id);
}
实现:UserDaoImpl.java
package mybatistest.dao.impl;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import mybatistest.dao.UserDao;
import mybatistest.entity.User;
@Repository
@Scope("prototype")
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
public String getUserString(String id) {
return "UserDao.getUserString";
}
public String insertUser(User user) {
String methodName = Thread.currentThread().getStackTrace()[1]
.getMethodName();
getSqlSession().insert(getClazz().getName() + "." + methodName, user);
return user.getUserID();
}
}
对应user.xml增加insertUser:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatistest.entity.User">
<resultMap id="userResultMap" type="mybatistest.entity.User">
<id property="userID" column="user_id" />
<result property="userNumber" column="user_number"/>
<result property="userName" column="user_name"/>
</resultMap>
<select id="getByID" parameterType="String" resultMap="userResultMap">
select user_id ,
user_number,
user_name,
remark
from system_users
where user_id = #{id}
</select>
<insert id="insertUser">
insert into system_users (user_id,user_number,user_name,remark)
values (#{userID},#{userNumber},#{userName},#{remark})
</insert>
</mapper>
再在Service中增加相应的方法:
package mybatistest.service.impl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import mybatistest.dao.UserDao;
import mybatistest.entity.User;
import mybatistest.service.UserService;
@Service
@Transactional
public class UserServiceImpl extends BaseServiceImpl<User, UserDao> implements
UserService {
public String userLogin(String userNumber, String userPassword) {
// ((UserDao) mainDao).getUserString("");
// 子类可以不用强制转换了
// getMainDao().getUserString("1");
User user = getMainDao().getByID("1");
if (null == user) {
return "用户不存在!";
}
if ("XXX" != userPassword) {
return "密码不正确!";
}
return "登录成功!";
}
public String insertUser(User user) {
// TODO Auto-generated method stub
getMainDao().insertUser(user);
return user.getUserID();
}
}
Test.java测试一下:
package mybatistest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import mybatistest.entity.User;
import mybatistest.service.UserService;
import mybatistest.service.impl.UserServiceImpl;
import mybatistest.utils.DaoHelper;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
//打印自动注册的类
for (String beanName:ac.getBeanDefinitionNames()){
System.out.println(beanName);
}
// 注意定义成接口,并通过getBean方式取得Bean
// UserService userService = (UserService) ac.getBean("userServiceImpl");
UserService userService = ac.getBean(UserService.class);
// 测试从接口中的服务取一个entity
User user = userService.getByID("1");
System.out.println(user.getUserName());
// 测试调接口的userLogin服务
System.out.println(userService.userLogin("1", "XXX"));
User newUser = new User();
newUser.setUserID(DaoHelper.getUUID());
newUser.setUserNumber("2");
newUser.setUserName("李四");
newUser.setRemark("");
userService.insertUser(newUser);
}
}
运行,然后到数据库,看到数据已插入了。个人理解应该是默认关闭Session时做了提交,或者是因为用了mybatis-spring,自己带了简单事务。
当然事务不是这么简单,很多情况下,会对多次操作数据库后,再统一提交或异常统一回滚。因此一般不是在原子级的数据库操作上加事务处理,而是在业务层加事务处理。这块参考了一下网上的资料,就直接采用注解事务来处理的了。
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" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" />
<property name="username" value="MyBatis" />
<property name="password" value="MyBatis" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-configuration.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<!-- 使用注解支持Bean注册 -->
<context:component-scan base-package="mybatistest" />
<!-- 使用注解支持事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- name表示以什么开始的方法名,比如 add*表示add开头的方法 propagation表示事务传播属性,不写默认有 -->
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="del*" />
<tx:method name="update*" />
<tx:method name="find*" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut expression="execution(* mybatistest.service..*.*(..))"
id="pointcut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
</beans>
增加了
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
同时配置了对Service层进行注解事务,对应Service层的实现类,需要增加@Transactional注解。
整体上这块有点复杂,内容也比较多,可以参考网上资料,注意理解到事务一致性的话,何时该用同一个事务,何时需要新开一个事务,了解一下spring的事务处理的几个基本属性,应该问题不大。
这种方式确实简化了很多,想以前都是try XX1,XX2,XX3,commit exception rollback end。