DTO、VO、POJO与实体类使用方案(结合Mapper.xml)

结合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 &lt;= #{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. 优化后的数据流转流程

  1. 前端请求Controller(接收DTO并校验)
  2. ControllerService(传递DTO)
  3. Service
    • 将DTO转换为Entity
    • 调用Mapper进行数据库操作
    • 将查询结果Entity转换为VO
  4. ServiceController(返回VO)
  5. Controller前端(返回VO数据)

7. 关键优化点

  1. Mapper.xml优化

    • 使用resultMap实现复杂结果映射
    • 动态SQL处理各种查询条件
    • 批量操作提高性能
  2. 对象转换优化

    • 在DTO/VO中定义转换方法
    • 使用链式调用简化代码
    • 静态工厂方法提高可读性
  3. 分页处理

    • 使用PageHelper实现物理分页
    • 统一分页返回结构
  4. 验证增强

    • 在DTO中使用更精细的验证注解
    • 密码复杂度验证
  5. 性能优化

    • 关联查询减少数据库访问次数
    • 批量插入提高效率

这种结构清晰地区分了各层职责,使代码更易维护和扩展,同时保证了良好的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值