小白第八篇 Spring+MyBatis使用数据库事务小实例
Spring+MyBatis小实例记录
- 运行环境
- Eclipse
MySql 8.0
Navicat Permium数据库视图管理工具
项目结构展示
数据库的设计比较简单,这里就只是对一张表进行了操作
搭建环境(配置spring-cfg.xml文件)
- PS:
- 因为使用的是MySQL 8.0 所以我这里的驱动配置是在com.mysql.cj.jdbc.Driver 但是如果是MySQL 5.0左右是com.mysql.jdbc.Driver
其次,需要注意的就是时区的问题,有时候会出错导致最后时间总是差了8个小时,但是我有时候运行又不会出错,纯粹的看概率?应该不是的吧!所以直接配置上去jdbc:mysql://localhost:3306/ssm?serverTimezone=GMT%2B8,这里的本来应该是GMT +8但是因为不能直接写+所以需要转义一下。
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 启用扫描机制 并指定扫描对象的包 -->
<context:annotation-config/>
<context:component-scan base-package="com.ww.ssm"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<!-- 时区的问题需要注意 serverTimezone=GMT+8 因为不能使用+号所以GMT%2B8就可以了 -->
<property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="maxActive" value="255"/>
<property name="maxIdle" value="5"/>
<property name="maxWait" value="10000"/>
</bean>
<!-- 集成MyBatis -->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 指定MyBatis的配置文件 -->
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/>
</bean>
<!-- 事务管理器配置数据事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 使用注解定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 采用自动扫描方式创建Mapper bean -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ww.ssm"/>
<property name="SqlSessionFactory" ref="SqlSessionFactory"/>
<property name="annotationClass" value="org.springframework.stereotype.Repository"/>
</bean>
</beans>
数据库表映射的POJO类
这个POJO类与数据库中对应的数据表字段对应的,这里是t_user表
public class User {
private long id;//数据的id
private String userName;//用户名
private String comment;//对于用户的注释信息
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
MyBatis的映射文件
建立SQL和POJO类之间的对应关系
<?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="com.ww.ssm.mapper.UserMapper">
<insert id="insertUser" parameterType="com.ww.ssm.pojo.User">
insert into t_user(userName,comment)
values(#{userName},#{comment})
</insert>
</mapper>
配置映射器使用映射文件内容
简单的配置一个接口就可以使用了!
@Repository
public interface UserMapper {
public int insertUser(User user);
}
引入这个映射器需要配置MyBatis的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<mapper resource="com/ww/ssm/mapper/UserMapper.xml"/>
</mappers>
</configuration>
配置服务类提供操作的功能
这里才用一个接口对应一个实现类的方式来定义服务类!
接口定义
/**
* 服务类接口 针对单个用户的操作
* @author WW
*
*/
public interface UserService {
public int insertUser(User user);
}
/**
* 服务类接口 针对多个用户的操作
* @author WW
*
*/
public interface UsersService {
public int insertUsers(List<User> list);
}
对应接口的实现类
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED)的注解指示了对应的隔离等级和传播行为,使得每一次当在调用多用户的方法的时候调用单个用户的处理方法每一次都会开启一个新事务,在发生异常导致回滚的时候也不会使得所有的操作都失败。
/**
* 实现单个用户操作的实现类
* @author WW
*
*/
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper = null;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW,
isolation = Isolation.READ_COMMITTED)
public int insertUser(User user) {
return userMapper.insertUser(user);
}
}
/**
* 多个用户操作的实现类
* @author WW
*
*/
@Service
public class UsersServiceImpl implements UsersService{
@Autowired
private UserService userService = null;
Logger log = Logger.getLogger(UserServiceImpl.class);
@Override
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED)
public int insertUsers(List<User> list) {
int count = 0;
for (User user : list) {
try {
count += userService.insertUser(user);
} catch (Exception e) {
log.info(e);
}
}
return count;
}
}
日志文件的配置
更好的输出对应的日志,这里是DEBUG级别的。
log4j.rootLogger=DEBUG , stdout
log4j.logger.org.springframework=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n
测试类的编写
public class Test {
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("spring-cfg.xml");
UsersService usersService = ctx.getBean(UsersService.class);
List<User> list = new ArrayList<User>();
for (int i = 1; i <= 2; i++) {
User user = new User();
user.setUserName("name_" + i);
user.setComment("comment_" + i);
list.add(user);
}
int count = usersService.insertUsers(list);
System.out.println(count);
}
}
这里是执行插入两条数据的行为来进行的测试
结果
.......
DEBUG 2019-03-21 22:14:01,957 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: insert into t_user(userName,comment) values(?,?)
DEBUG 2019-03-21 22:14:02,001 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: name_1(String), comment_1(String)
DEBUG 2019-03-21 22:14:02,014 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <== Updates: 1
.......
DEBUG 2019-03-21 22:14:02,133 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: insert into t_user(userName,comment) values(?,?)
DEBUG 2019-03-21 22:14:02,134 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: name_2(String), comment_2(String)
DEBUG 2019-03-21 22:14:02,158 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <== Updates: 1
.......
DEBUG 2019-03-21 22:14:02,276 org.springframework.jdbc.datasource.DataSourceUtils: Returning JDBC Connection to DataSource
2
最后的结果显示修改了两条数据,这个时候我们可以去数据库看一看实际的数据插入的情况:
操作是成功的,这里的id是设置的自动增长,所以没有进行赋值,而后面的两个字段都是我操作的数据。
完成啦!!!!
也是首次对于Spring+MyBatis进行了整合,和之前分开学的不同的是只有在对一个实例中同时用到这些东西的时候你才知道它们各自所发挥的作用,虽然这个例子很小但是也表达出了一些两个框架的用法和思想!!