跳转到内容

MyBatis 集成

本教程将指导你在 Feat Cloud 中集成 MyBatis,构建一个完整的用户管理系统。

  • 配置 MyBatis 环境
  • 创建数据库表结构
  • 实现数据访问层(Mapper)
  • 构建业务逻辑层(Service)
  • 创建 REST API 控制器

有关完整示例,请参见 Gitee 仓库中的 MyBatis 示例

pom.xml 中添加以下依赖:

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.15</version>
</dependency>
<!-- 使用 H2 内存数据库演示 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
</dependency>

src/main/resources 目录下创建 feat.yaml

feat:
mybatis:
path: mybatis/mybatis-config.xml
initial-sql: mybatis/ddl/schema.sql

配置项说明:

配置项必填说明
feat.mybatis.pathMyBatis XML 配置文件路径,相对于 src/main/resources
feat.mybatis.initial-sql数据库初始化 SQL 脚本路径,应用启动时自动执行

src/main/resources/mybatis 目录下创建 mybatis-config.xml

mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="h2_mem">
<environment id="h2_mem">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:feat-demo;NON_KEYWORDS=value;mode=mysql;"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="tech.smartboot.feat.demo.mybatis.mapper"/>
</mappers>
</configuration>

src/main/resources/mybatis/ddl 目录下创建 schema.sql

schema.sql
-- 用户信息表
CREATE TABLE IF NOT EXISTS user_info
(
username varchar(32) NOT NULL COMMENT '用户名',
password varchar(128) NOT NULL COMMENT '密码',
`desc` varchar(256) COMMENT '备注',
role varchar(32) COMMENT '角色',
create_time timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
edit_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_user_password (username, password),
PRIMARY KEY (username)
);
-- 插入初始数据
INSERT IGNORE INTO user_info(username, password, role, `desc`)
VALUES ('feat', 'feat', 'admin', '超级账户');
INSERT IGNORE INTO user_info(username, password, role, `desc`)
VALUES ('admin', 'admin123', 'admin', '管理员用户');
Bootstrap.java
@Bean
public class Bootstrap {
public static void main(String[] args) {
FeatCloud.cloudServer().listen();
}
}

创建 User 实体类,对应数据库中的 user_info 表:

User.java
public class User {
private String username;
private String password;
private String desc;
private String role;
private Date createTime;
private Date editTime;
// 构造函数
public User() {}
public User(String username, String password, String desc, String role) {
this.username = username;
this.password = password;
this.desc = desc;
this.role = role;
}
// getter 和 setter 方法
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public Date getCreateTime() { return createTime; }
public void setCreateTime(Date createTime) { this.createTime = createTime; }
public Date getEditTime() { return editTime; }
public void setEditTime(Date editTime) { this.editTime = editTime; }
}

使用 MyBatis 注解方式定义 UserMapper 接口:

UserMapper.java
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user_info WHERE username = #{username}")
@Results({
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "desc", column = "desc"),
@Result(property = "role", column = "role"),
@Result(property = "createTime", column = "create_time"),
@Result(property = "editTime", column = "edit_time")
})
User selectByUsername(@Param("username") String username);
@Select("SELECT * FROM user_info")
@Results({
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "desc", column = "desc"),
@Result(property = "role", column = "role"),
@Result(property = "createTime", column = "create_time"),
@Result(property = "editTime", column = "edit_time")
})
List<User> selectAll();
@Insert("INSERT INTO user_info(username, password, `desc`, role) VALUES(#{username}, #{password}, #{desc}, #{role})")
int insert(User user);
@Update("UPDATE user_info SET password=#{password}, `desc`=#{desc}, role=#{role} WHERE username=#{username}")
int update(User user);
@Delete("DELETE FROM user_info WHERE username = #{username}")
int deleteByUsername(@Param("username") String username);
@Select("SELECT * FROM user_info WHERE role = #{role}")
@Results({
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "desc", column = "desc"),
@Result(property = "role", column = "role"),
@Result(property = "createTime", column = "create_time"),
@Result(property = "editTime", column = "edit_time")
})
List<User> selectByRole(@Param("role") String role);
}

创建 UserService 类处理业务逻辑:

UserService.java
@Bean
public class UserService {
@Autowired
private UserMapper userMapper;
public User findByUsername(String username) {
return userMapper.selectByUsername(username);
}
public List<User> findAll() {
return userMapper.selectAll();
}
public List<User> findByRole(String role) {
return userMapper.selectByRole(role);
}
public boolean insert(User user) {
try {
return userMapper.insert(user) > 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean update(User user) {
try {
return userMapper.update(user) > 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean deleteByUsername(String username) {
try {
return userMapper.deleteByUsername(username) > 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}

创建 UserController 类提供 RESTful API:

UserController.java
@Controller
public class UserController {
@Autowired
private UserService userService;
// 获取所有用户
@RequestMapping("/users")
public RestResult<List<User>> getAllUsers() {
List<User> users = userService.findAll();
return RestResult.ok(users);
}
// 根据用户名获取用户
@RequestMapping("/users/{username}")
public RestResult<User> getUserByUsername(@PathParam("username") String username) {
User user = userService.findByUsername(username);
if (user != null) {
return RestResult.ok(user);
} else {
return RestResult.fail("User not found");
}
}
// 根据角色获取用户
@RequestMapping("/users/role/{role}")
public RestResult<List<User>> getUsersByRole(@PathParam("role") String role) {
List<User> users = userService.findByRole(role);
return RestResult.ok(users);
}
// 创建用户
@RequestMapping(value = "/users", method = RequestMethod.POST)
public RestResult<String> createUser(User user) {
boolean success = userService.insert(user);
return success ? RestResult.ok("User created successfully")
: RestResult.fail("Failed to create user");
}
// 更新用户
@RequestMapping(value = "/users", method = RequestMethod.PUT)
public RestResult<String> updateUser(User user) {
boolean success = userService.update(user);
return success ? RestResult.ok("User updated successfully")
: RestResult.fail("Failed to update user");
}
// 删除用户
@RequestMapping(value = "/users/{username}", method = RequestMethod.DELETE)
public RestResult<String> deleteUser(@PathParam("username") String username) {
boolean success = userService.deleteByUsername(username);
return success ? RestResult.ok("User deleted successfully")
: RestResult.fail("Failed to delete user");
}
}

启动应用后,可以通过以下 HTTP 请求测试 API:

### 获取所有用户
GET http://localhost:8080/users
### 根据用户名获取特定用户
GET http://localhost:8080/users/feat
### 根据角色获取用户列表
GET http://localhost:8080/users/role/admin
### 创建新用户
POST http://localhost:8080/users
Content-Type: application/json
{
"username": "newuser",
"password": "password123",
"desc": "New test user",
"role": "user"
}
### 更新用户信息
PUT http://localhost:8080/users
Content-Type: application/json
{
"username": "newuser",
"password": "newpassword123",
"desc": "Updated test user",
"role": "user"
}
### 删除特定用户
DELETE http://localhost:8080/users/newuser

Feat Cloud 在编译期解析 feat.yaml 和 MyBatis XML 配置,自动生成 SqlSessionFactory Bean。生成的 SqlSessionFactory Bean 名称为 sessionFactory,可直接注入使用。

数据流转过程:

客户端 -> Controller层 -> Service层 -> Mapper层 -> 数据库

使用日志记录异常,而非简单打印堆栈:

public boolean insert(User user) {
try {
return userMapper.insert(user) > 0;
} catch (Exception e) {
LOGGER.error("Failed to insert user: " + user.getUsername(), e);
return false;
}
}

Feat Cloud 暂不提供事务注解,需要手动管理事务:

@Bean
public class UserService {
@Autowired
private SqlSessionFactory sessionFactory;
public boolean batchInsert(List<User> users) {
SqlSession sqlSession = sessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
for (User user : users) {
userMapper.insert(user);
}
sqlSession.commit();
return true;
} catch (Exception e) {
sqlSession.rollback();
LOGGER.error("Failed to batch insert users", e);
return false;
} finally {
sqlSession.close();
}
}
}

对于可能返回大量数据的查询,实现分页功能:

@Select("SELECT * FROM user_info LIMIT #{offset}, #{limit}")
@Results({
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "desc", column = "desc"),
@Result(property = "role", column = "role"),
@Result(property = "createTime", column = "create_time"),
@Result(property = "editTime", column = "edit_time")
})
List<User> selectWithPagination(@Param("offset") int offset, @Param("limit") int limit);

通过本教程,你已经学会了:

  1. 配置 MyBatis 环境和数据库连接
  2. 创建数据库表结构和初始化数据
  3. 实现实体类、Mapper 接口、Service 类和 Controller 类
  4. 构建 RESTful API 接口
  5. 测试 API 功能

这种分层架构使代码更加清晰,便于维护和扩展。