结合MyBatis的Mapper.xml文件,展示完整的层级数据流转和数据库操作。
1. 实体类优化(Entity)
// User.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_user")
public class User {
@TableId(type = IdType.AUTO)
private Long userId;
@NotBlank
private String username;
@NotBlank
private String password;
private String email;
private String phone;
private Date createTime;
// 非数据库字段,用于关联查询
@TableField(exist = false)
private List<Role> roles;
}
// Role.java
@Data
@TableName("sys_role")
public class Role {
@TableId(type = IdType.AUTO)
private Long roleId;
private String roleName;
private String roleDesc;
}
2. Mapper接口与XML配置
UserMapper.java
@Mapper
public interface UserMapper {
// 插入用户并返回主键
int insertUser(User user);
// 根据ID查询用户(包含角色信息)
User selectUserWithRoles(@Param("userId") Long userId);
// 分页查询用户
List<User> selectUserList(UserQueryDTO queryDTO);
// 批量插入用户角色关系
int batchInsertUserRoles(@Param("list") List<UserRole> userRoles);
}
UserMapper.xml
<?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.example.mapper.UserMapper">
<!-- 基本结果映射 -->
<resultMap id="BaseUserMap" type="com.example.entity.User">
<id column="user_id" property="userId"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="email" property="email"/>
<result column="phone" property="phone"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 包含角色信息的用户映射 -->
<resultMap id="UserWithRolesMap" type="com.example.entity.User" extends="BaseUserMap">
<collection property="roles" ofType="com.example.entity.Role">
<id column="role_id" property="roleId"/>
<result column="role_name" property="roleName"/>
<result column="role_desc" property="roleDesc"/>
</collection>
</resultMap>
<!-- 插入用户 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="userId">
INSERT INTO sys_user (username, password, email, phone)
VALUES (#{username}, #{password}, #{email}, #{phone})
</insert>
<!-- 查询用户及其角色 -->
<select id="selectUserWithRoles" resultMap="UserWithRolesMap">
SELECT
u.*,
r.role_id, r.role_name, r.role_desc
FROM
sys_user u
LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id
LEFT JOIN sys_role r ON ur.role_id = r.role_id
WHERE
u.user_id = #{userId}
</select>
<!-- 动态查询用户列表 -->
<select id="selectUserList" resultMap="BaseUserMap">
SELECT * FROM sys_user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
<if test="phone != null and phone != ''">
AND phone = #{phone}
</if>
<if test="createTimeStart != null">
AND create_time >= #{createTimeStart}
</if>
<if test="createTimeEnd != null">
AND create_time <= #{createTimeEnd}
</if>
</where>
ORDER BY create_time DESC
</select>
<!-- 批量插入用户角色关系 -->
<insert id="batchInsertUserRoles">
INSERT INTO sys_user_role (user_id, role_id)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.roleId})
</foreach>
</insert>
</mapper>
3. 服务层优化实现
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserMapper userMapper;
private final RoleMapper roleMapper;
private final PasswordEncoder passwordEncoder;
@Override
@Transactional
public UserVO createUser(UserDTO userDTO) {
// DTO转Entity
User user = new User();
BeanUtils.copyProperties(userDTO, user);
// 密码加密
user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
// 保存用户
userMapper.insertUser(user);
// 保存用户角色关系
if (!CollectionUtils.isEmpty(userDTO.getRoleIds())) {
List<UserRole> userRoles = userDTO.getRoleIds().stream()
.map(roleId -> new UserRole(user.getUserId(), roleId))
.collect(Collectors.toList());
userMapper.batchInsertUserRoles(userRoles);
}
// 返回完整的用户信息
return getUserVO(user.getUserId());
}
@Override
public PageVO<UserVO> getUsers(UserQueryDTO queryDTO) {
// 设置分页参数
PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
// 查询用户列表
List<User> users = userMapper.selectUserList(queryDTO);
PageInfo<User> pageInfo = new PageInfo<>(users);
// 转换为VO列表
List<UserVO> userVOs = users.stream()
.map(user -> UserVO.fromEntity(user, getRolesByUserId(user.getUserId())))
.collect(Collectors.toList());
// 构建分页VO
return new PageVO<>(
pageInfo.getTotal(),
pageInfo.getPageNum(),
pageInfo.getPageSize(),
userVOs
);
}
@Override
public UserVO getUserVO(Long userId) {
User user = userMapper.selectUserWithRoles(userId);
return UserVO.fromEntity(user, user.getRoles());
}
private List<Role> getRolesByUserId(Long userId) {
return roleMapper.selectByUserId(userId);
}
}
4. DTO/VO优化设计
UserDTO.java
@Data
public class UserDTO {
@NotBlank(message = "用户名不能为空")
@Size(min = 4, max = 20)
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20)
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d).*$",
message = "密码必须包含字母和数字")
private String password;
@Email
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$")
private String phone;
@NotEmpty(message = "至少分配一个角色")
private List<Long> roleIds;
// 自定义转换方法
public User toEntity() {
User user = new User();
BeanUtils.copyProperties(this, user);
return user;
}
}
UserVO.java
@Data
@Accessors(chain = true)
public class UserVO {
private Long userId;
private String username;
private String email;
private String phone;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
private List<RoleVO> roles;
// 静态工厂方法
public static UserVO fromEntity(User user, List<Role> roles) {
return new UserVO()
.setUserId(user.getUserId())
.setUsername(user.getUsername())
.setEmail(user.getEmail())
.setPhone(user.getPhone())
.setCreateTime(user.getCreateTime())
.setRoles(roles.stream()
.map(RoleVO::fromEntity)
.collect(Collectors.toList()));
}
}
PageVO.java (通用分页VO)
@Data
@AllArgsConstructor
public class PageVO<T> {
private Long total;
private Integer pageNum;
private Integer pageSize;
private List<T> list;
// 计算总页数
public Integer getPages() {
if (pageSize == 0) return 0;
return (int) Math.ceil((double) total / pageSize);
}
}
5. 控制器层优化
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping
public ResponseEntity<Result<UserVO>> createUser(
@Valid @RequestBody UserDTO userDTO) {
UserVO userVO = userService.createUser(userDTO);
return ResponseEntity.ok(Result.success(userVO));
}
@GetMapping
public ResponseEntity<Result<PageVO<UserVO>>> getUsers(
@Valid UserQueryDTO queryDTO) {
PageVO<UserVO> page = userService.getUsers(queryDTO);
return ResponseEntity.ok(Result.success(page));
}
@GetMapping("/{userId}")
public ResponseEntity<Result<UserVO>> getUser(
@PathVariable Long userId) {
UserVO userVO = userService.getUserVO(userId);
return ResponseEntity.ok(Result.success(userVO));
}
}
// 通用返回结果
@Data
@AllArgsConstructor
class Result<T> {
private int code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
}
6. 优化后的数据流转流程
- 前端请求 → Controller(接收DTO并校验)
- Controller → Service(传递DTO)
- Service:
- 将DTO转换为Entity
- 调用Mapper进行数据库操作
- 将查询结果Entity转换为VO
- Service → Controller(返回VO)
- Controller → 前端(返回VO数据)
7. 关键优化点
-
Mapper.xml优化:
- 使用
resultMap
实现复杂结果映射 - 动态SQL处理各种查询条件
- 批量操作提高性能
- 使用
-
对象转换优化:
- 在DTO/VO中定义转换方法
- 使用链式调用简化代码
- 静态工厂方法提高可读性
-
分页处理:
- 使用PageHelper实现物理分页
- 统一分页返回结构
-
验证增强:
- 在DTO中使用更精细的验证注解
- 密码复杂度验证
-
性能优化:
- 关联查询减少数据库访问次数
- 批量插入提高效率
这种结构清晰地区分了各层职责,使代码更易维护和扩展,同时保证了良好的性能。