Spring Boot+MyBatis+Atomikos+MySQL「附源码」

1. 项目简介

本篇文章将会介绍如何将Spring Boot、MyBatis、Atomikos、MySQL这几个框架和数据库组合起来构建一个分布式事务应用。本项目实现了一个简单的用户注册功能,其中包括了数据库的读写操作。在本项目中,我们使用了Spring Boot作为应用框架,MyBatis作为ORM框架,Atomikos作为分布式事务管理器,MySQL作为存储数据库。

2. 准备工作

2.1 创建Spring Boot项目

首先,我们需要创建一个Spring Boot项目。可以使用IDE工具(如IDEA或Eclipse)创建一个Spring Boot项目。也可以使用Spring Initializr创建一个空的Spring Boot项目。这里我们使用Spring Initializr创建一个Spring Boot项目,并添加Web和MyBatis的依赖。

在pom.xml文件中添加以下依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.0.1</version>

</dependency>

2.2 创建MySQL数据库

接下来,我们需要在本地创建一个MySQL数据库。可以使用命令行工具或使用第三方工具(如Navicat或MySQL Workbench等)创建一个MySQL数据库。本项目需要创建一个名为“test”的数据库,并在该数据库中创建一个名为“user”的表,表结构如下:

CREATE TABLE `user` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`name` varchar(255) NOT NULL,

`age` int(11) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

3. 配置MyBatis

在完成上述准备工作后,接下来我们需要配置MyBatis。在Spring Boot项目中,MyBatis自动配置是开启的,我们只需要在application.properties文件中进行相关配置即可。在本项目中,我们使用了MySQL数据库作为存储数据库,所以需要进行如下配置:

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

spring.datasource.username=root

spring.datasource.password=123456

mybatis.config-location=classpath:mybatis-config.xml

mybatis.mapper-locations=classpath:mapper/*.xml

其中,mybatis-config.xml文件用于配置MyBatis,可以在其中添加一些自定义的配置,比如类型别名、插件等。在本项目中,mybatis-config.xml文件内容如下:

<configuration>

<typeAliases>

<typeAlias type="com.example.demo.entity.User" alias="User"/>

</typeAliases>

</configuration>

mapper目录中,我们需要为User实体创建相应的Mapper文件,并编写SQL语句。在本项目中,我们创建了一个名为UserMapper.xml的Mapper文件,内容如下:

<mapper namespace="com.example.demo.mapper.UserMapper">

<resultMap id="BaseResultMap" type="User">

<id column="id" property="id" jdbcType="INTEGER"/>

<result column="name" property="name" jdbcType="VARCHAR"/>

<result column="age" property="age" jdbcType="INTEGER"/>

</resultMap>

<select id="selectAll" resultMap="BaseResultMap">

select * from user

</select>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">

insert into user (name, age)

values (#{name}, #{age})

</insert>

</mapper>

4. 配置Atomikos

接下来,我们需要配置Atomikos。Atomikos是一个Java事务管理框架,可以帮助我们管理分布式事务。在本项目中,我们需要将MySQL数据库配置为一个XA数据源,然后再将它注册到Atomikos中。

4.1 添加Atomikos的依赖

在pom.xml文件中添加Atomikos的依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jta-atomikos</artifactId>

<version>2.5.0</version>

</dependency>

上面的依赖包含了Spring框架的JTA和Atomikos的相关类。

4.2 配置数据库为XA数据源

application.properties文件中添加以下内容,将MySQL数据库配置为XA数据源:

spring.datasource.unique-resource-name=myDataSource

spring.datasource.xa.dataSourceClassName=com.mysql.cj.jdbc.MysqlXADataSource

spring.datasource.xa.properties.user=root

spring.datasource.xa.properties.password=123456

spring.datasource.xa.properties.URL=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

spring.datasource.xa.properties.cachePrepStmts=true

spring.datasource.xa.properties.cachePrepStmtsSize=250

spring.datasource.xa.properties.prepStmtCacheSqlLimit=2048

spring.datasource.xa.properties.useServerPrepStmts=true

4.3 写Atomikos的配置文件

接下来,我们需要为Atomikos创建一个配置文件atomikos.properties,并配置JTA的相关参数。在项目的src/main/resources目录下创建一个文件夹config,并在该目录下创建atomikos.properties文件。内容如下:

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory

com.atomikos.icatch.log_base_dir=./XATransactionLogs

com.atomikos.icatch.automatic_resource_registration=true

java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory

java.naming.provider.url=rmi://127.0.0.1:1099/

com.atomikos.icatch.max_timeout=60

上面的配置文件中,com.atomikos.icatch.service参数是必须的,表示使用Atomikos的事务管理器;com.atomikos.icatch.log_base_dir参数表示事务日志的存储路径;com.atomikos.icatch.automatic_resource_registration参数表示注册分布式资源时,是否自动启用重试机制;java.naming.factory.initialjava.naming.provider.url两个参数为JNDI的引用,用于指定Atomikos的JNDI服务地址和端口号;com.atomikos.icatch.max_timeout参数表示事务最大超时时间,单位为秒。

4.4 配置JTA

最后,在application.properties文件中添加以下内容,配置使用JTA分布式事务管理器:

spring.datasource.type=com.atomikos.jdbc.AtomikosDataSourceBean

spring.jta.atomikos.datasource.unique-resource-name=myDataSource

mybatis.configuration.map-underscore-to-camel-case=true

mybatis.configuration.default-fetch-size=100

mybatis.configuration.default-statement-timeout=3000

mybatis.configuration.cache-enabled=false

mybatis.executor-type=batch

上面的配置文件中,spring.datasource.type参数表示使用AtomikosDataSourceBean作为数据源,从而使用Atomikos管理分布式事务;spring.jta.atomikos.datasource.unique-resource-name参数表示JTA中的数据源名称,且必须与spring.datasource.unique-resource-name参数保持一致。

5. 编写Java代码

现在,我们已经完成了Spring Boot、MyBatis、Atomikos、MySQL的配置,接下来就是编写Java代码了。

5.1 创建实体类

首先,我们需要创建一个实体类User,用于映射user表中的记录。实体类代码如下:

public class User {

private Integer id;

private String name;

private Integer age;

// getter and setter methods

}

5.2 创建Mapper接口

接下来,我们需要创建一个Mapper接口UserMapper,用于将Java对象与SQL语句进行映射。Mapper接口代码如下:

@Mapper

public interface UserMapper {

@Select("select * from user")

List<User> selectAll();

@Insert("insert into user (name, age) values (#{name}, #{age})")

@Options(useGeneratedKeys = true, keyProperty = "id")

Integer insert(User user);

}

在上面的UserMapper接口中,我们使用@Mapper注解表示该接口为Mapper接口,然后定义了两个方法selectAllinsert,分别对应于user表中的查询和插入操作。由于插入操作需要返回自增主键的值,因此使用了@Options注解。

5.3 创建Service实现类

接下来,我们需要创建一个Service实现类UserServiceImpl,用于实现业务逻辑。在该类中,我们需要将业务逻辑包装在一个分布式事务中。Service实现类代码如下:

@Slf4j

@Service

@Transactional(rollbackFor = Exception.class)

public class UserServiceImpl implements UserService {

@Autowired

private UserMapper userMapper;

@Override

public List<User> selectAll() {

return userMapper.selectAll();

}

@Override

public Integer insert(User user) {

return userMapper.insert(user);

}

}

上面的代码中,我们首先使用@Slf4j注解创建一个log对象,用于输出日志。然后,使用@Service注解表示该类为Service实现类,使用@Transactional注解表示将该类中所有方法都包装在一个分布式事务中处理。最后,我们使用@Autowired注解自动注入UserMapper,并实现了selectAllinsert两个方法。

5.4 创建Controller类

最后,我们需要创建一个Controller类UserController,用于接收外部请求并调用Service中的方法。Controller类代码如下:

@RestController

@RequestMapping("/user")

public class UserController {

@Autowired

private UserService userService;

@GetMapping("/selectAll")

public List<User> selectAll() {

return userService.selectAll();

}

@PostMapping("/insert")

public Integer insert(@RequestBody User user) {

return userService.insert(user);

}

}

上面的代码中,我们使用@RestController注解表示该类为Controller类,并使用@RequestMapping注解设置请求路径。然后,使用@Autowired注解自动注入UserService,并实现了查询和插入操作的接口方法。

6. 测试

现在,我们已经完成了各种配置和代码的编写工作,接下来可以启动Spring Boot应用,测试它是否能正常工作。可以使用Postman或其他API工具,向接口/user/selectAll发送GET请求,查询数据库中已经有的用户信息。也可以使用接口/user/insert创建新用户信息,将新用户信息插入数据库。如果一切正常,我们就成功地创建了一个使用Spring Boot+MyBatis+Atomikos+MySQL的分布式事务应用。

后端开发标签