我现在有两个表,是一对多的关系,CREATE TABLE repayment_plan (
,针对一个还款计划可多次进行还款'; 下面请帮我映射成两个bean对象

ID bigint(20) NOT NULL COMMENT '主键',
CONSUMER_ID bigint(20) DEFAULT NULL COMMENT '发标人用户标识',
USER_NO varchar(50) DEFAULT NULL COMMENT '发标人用户编码',
PROJECT_ID bigint(20) DEFAULT NULL COMMENT '标的标识',
PROJECT_NO varchar(50) DEFAULT NULL COMMENT '标的编码',
NUMBER_OF_PERIODS int(11) DEFAULT NULL COMMENT '期数',
INTEREST decimal(10,2) DEFAULT NULL COMMENT '还款利息',
PRINCIPAL decimal(10,2) DEFAULT NULL COMMENT '还款本金',
AMOUNT decimal(10,2) DEFAULT NULL COMMENT '本息',
SHOULD_REPAYMENT_DATE datetime DEFAULT NULL COMMENT '应还时间',
REPAYMENT_STATUS varchar(50) DEFAULT NULL COMMENT '应还状态0.待还,1.已还, 2.部分还款',
CREATE_DATE datetime DEFAULT NULL COMMENT '计划创建时间',
COMMISSION decimal(10,2) DEFAULT NULL COMMENT '年化利率(平台佣金,利差)',
PRIMARY KEY (ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='借款人还款计划';

CREATE TABLE repayment_detail (
ID bigint(20) NOT NULL COMMENT '主键',
REPAYMENT_PLAN_ID bigint(20) DEFAULT NULL COMMENT '还款计划项标识',
AMOUNT decimal(10,2) DEFAULT NULL COMMENT '实还本息',
REPAYMENT_DATE datetime DEFAULT NULL COMMENT '实际还款时间',
REQUEST_NO varchar(50) DEFAULT NULL COMMENT '冻结用户资金请求流水号(用于解冻合并整体还款),
STATUS tinyint(4) DEFAULT NULL COMMENT '可用状态',
PRIMARY KEY (ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='借款人还款明细

以下是对应的Java Bean对象:

  1. RepaymentPlan.java
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class RepaymentPlan {

    private Long id;

    private Long consumerId;

    private String userNo;

    private Long projectId;

    private String projectNo;

    private Integer numberOfPeriods;

    private BigDecimal interest;

    private BigDecimal principal;

    private BigDecimal amount;

    private LocalDateTime shouldRepaymentDate;

    private String repaymentStatus;

    private LocalDateTime createDate;

    private BigDecimal commission;

    // getter 和 setter 略
}
  1. RepaymentDetail.java
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class RepaymentDetail {

    private Long id;

    private Long repaymentPlanId;

    private BigDecimal amount;

    private LocalDateTime repaymentDate;

    private String requestNo;

    private Integer status;

    // getter 和 setter 略
}

我所使用的是mybatisPlus,我想查询RepaymentPlanDTO,这个DTO有一个属性List<RepaymentDetailDTO>, 一对多, java代码如何实现

好的,如果使用MybatisPlus,则需要先定义对应的MybatisPlus相关的Mapper接口和XML文件,考虑到你的需求,以下是对应的Mapper和XML的代码示例:

  1. RepaymentPlanMapper.java
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface RepaymentPlanMapper extends BaseMapper<RepaymentPlan> {
    
    // 定义方法查询RepaymentPlanDTO及对应的RepaymentDetailDTO列表
    List<RepaymentPlanDTO> selectRepaymentPlanWithDetail();
}
  1. repayment_plan.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.RepaymentPlanMapper">

    <resultMap id="repaymentPlanResultMap" type="com.example.dto.RepaymentPlanDTO" >
        <!-- 主表字段映射 -->
        <id property="id" column="ID" />
        <result property="consumerId" column="CONSUMER_ID" />
        <result property="userNo" column="USER_NO" />
        <result property="projectId" column="PROJECT_ID" />
        <result property="projectNo" column="PROJECT_NO" />
        <result property="numberOfPeriods" column="NUMBER_OF_PERIODS" />
        <result property="interest" column="INTEREST" />
        <result property="principal" column="PRINCIPAL" />
        <result property="amount" column="AMOUNT" />
        <result property="shouldRepaymentDate" column="SHOULD_REPAYMENT_DATE" />
        <result property="repaymentStatus" column="REPAYMENT_STATUS" />
        <result property="createDate" column="CREATE_DATE" />
        <result property="commission" column="COMMISSION" />
        <!-- 一对多关联字段映射 -->
        <collection property="repaymentDetailList" ofType="com.example.dto.RepaymentDetailDTO" >
            <id property="id" column="DETAIL_ID" />
            <result property="repaymentPlanId" column="RP_ID" />
            <result property="amount" column="DETAIL_AMOUNT" />
            <result property="repaymentDate" column="REPAYMENT_DATE" />
            <result property="requestNo" column="REQUEST_NO" />
            <result property="status" column="STATUS" />
        </collection>
    </resultMap>

    <select id="selectRepaymentPlanWithDetail" resultMap="repaymentPlanResultMap" >
        SELECT 
        rp.ID, rp.CONSUMER_ID, rp.USER_NO, rp.PROJECT_ID, rp.PROJECT_NO, rp.NUMBER_OF_PERIODS, rp.INTEREST,
        rp.PRINCIPAL, rp.AMOUNT, rp.SHOULD_REPAYMENT_DATE, rp.REPAYMENT_STATUS, rp.CREATE_DATE, rp.COMMISSION,
        rd.ID AS DETAIL_ID, rd.REPAYMENT_PLAN_ID AS RP_ID, rd.AMOUNT AS DETAIL_AMOUNT, rd.REPAYMENT_DATE, 
        rd.REQUEST_NO, rd.STATUS
        FROM repayment_plan rp LEFT JOIN repayment_detail rd ON rd.REPAYMENT_PLAN_ID=rp.ID
    </select>

</mapper>
  1. RepaymentPlanDTO.java
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

public class RepaymentPlanDTO {

    private Long id;

    private Long consumerId;

    private String userNo;

    private Long projectId;

    private String projectNo;

    private Integer numberOfPeriods;

    private BigDecimal interest;

    private BigDecimal principal;

    private BigDecimal amount;

    private LocalDateTime shouldRepaymentDate;

    private String repaymentStatus;

    private LocalDateTime createDate;

    private BigDecimal commission;

    // 一对多关联属性
    private List<RepaymentDetailDTO> repaymentDetailList;

    // getter 和 setter 略
}
  1. RepaymentDetailDTO.java
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class RepaymentDetailDTO {

    private Long id;

    private Long repaymentPlanId;

    private BigDecimal amount;

    private LocalDateTime repaymentDate;

    private String requestNo;

    private Integer status;

    // getter 和 setter 略
}

在Java代码中使用的话,调用RepaymentPlanMapper中定义的方法可以直接查询出RepaymentPlanDTO及对应的RepaymentDetailDTO列表,示例代码如下:

@Autowired
private RepaymentPlanMapper repaymentPlanMapper;

// 查询RepaymentPlanDTO及对应的RepaymentDetailDTO列表
List<RepaymentPlanDTO> repaymentPlanList = repaymentPlanMapper.selectRepaymentPlanWithDetail();

下面是一对一:

如果是一对一的关系,则需要对应修改Mapper接口、XML文件以及对应的DTO类。

下面以还款计划和借款人信息为例,示例代码如下:

  1. RepaymentPlanMapper.java
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface RepaymentPlanMapper extends BaseMapper<RepaymentPlan> {
    
     // 定义方法查询RepaymentPlanDTO及对应的UserInfoDTO
    List<RepaymentPlanDTO> selectRepaymentPlanWithUserInfo();
}
  1. repayment_plan.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.RepaymentPlanMapper">

    <resultMap id="repaymentPlanResultMap" type="com.example.dto.RepaymentPlanDTO" >
        <!-- 主表字段映射 -->
        <id property="id" column="ID" />
        <result property="consumerId" column="CONSUMER_ID" />
        <result property="userNo" column="USER_NO" />
        <result property="projectId" column="PROJECT_ID" />
        <result property="projectNo" column="PROJECT_NO" />
        <result property="numberOfPeriods" column="NUMBER_OF_PERIODS" />
        <result property="interest" column="INTEREST" />
        <result property="principal" column="PRINCIPAL" />
        <result property="amount" column="AMOUNT" />
        <result property="shouldRepaymentDate" column="SHOULD_REPAYMENT_DATE" />
        <result property="repaymentStatus" column="REPAYMENT_STATUS" />
        <result property="createDate" column="CREATE_DATE" />
        <result property="commission" column="COMMISSION" />
        <!-- 一对一关联字段映射 -->
        <association property="userInfo" javaType="com.example.dto.UserInfoDTO">
            <id property="id" column="USER_ID"/>
            <result property="userName" column="USER_NAME" />
            <result property="mobileNo" column="MOBILE_NO" />
        </association>
    </resultMap>

    <select id="selectRepaymentPlanWithUserInfo" resultMap="repaymentPlanResultMap" >
        SELECT 
        rp.ID, rp.CONSUMER_ID, rp.USER_NO, rp.PROJECT_ID, rp.PROJECT_NO, rp.NUMBER_OF_PERIODS, rp.INTEREST,
        rp.PRINCIPAL, rp.AMOUNT, rp.SHOULD_REPAYMENT_DATE, rp.REPAYMENT_STATUS, rp.CREATE_DATE, rp.COMMISSION,
        ui.ID AS USER_ID, ui.USER_NAME, ui.MOBILE_NO
        FROM repayment_plan rp LEFT JOIN user_info ui ON ui.ID=rp.USER_ID
    </select>

</mapper>
  1. RepaymentPlanDTO.java
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class RepaymentPlanDTO {

    private Long id;

    private Long consumerId;

    private String userNo;

    private Long projectId;

    private String projectNo;

    private Integer numberOfPeriods;

    private BigDecimal interest;

    private BigDecimal principal;

    private BigDecimal amount;

    private LocalDateTime shouldRepaymentDate;

    private String repaymentStatus;

    private LocalDateTime createDate;

    private BigDecimal commission;

    // 一对一关联属性
    private UserInfoDTO userInfo;

    // getter 和 setter 略
}
  1. UserInfoDTO.java
public class UserInfoDTO {

    private Long id;

    private String userName;

    private String mobileNo;

    // getter 和 setter 略
}

然后在Java代码中调用RepaymentPlanMapper中定义的方法即可查询出RepaymentPlanDTO和对应的UserInfoDTO,示例代码如下:

@Autowired
private RepaymentPlanMapper repaymentPlanMapper;

// 查询RepaymentPlanDTO和对应的UserInfoDTO
List<RepaymentPlanDTO> repaymentPlanList = repaymentPlanMapper.selectRepaymentPlanWithUserInfo();

下面是mybatisplus的代码;

                多实例

使用BeanUtils.copyProperties进行对象复制:

public List<PlanDTO> getPlanDTOList() {
    List<PlanDTO> planDTOList = new ArrayList<>();
    QueryWrapper<RepaymentPlan> planQueryWrapper = new QueryWrapper<>();
    planQueryWrapper.select("id", "consumer_id", "user_no", "project_id", "project_no", "number_of_periods", "interest", "principal", "amount", "should_repayment_date", "repayment_status", "create_date", "commission")
            .eq("t1.xxx", "xxx");
    List<RepaymentPlan> planList = repaymentPlanMapper.selectList(planQueryWrapper);

    for(RepaymentPlan plan : planList) {
        PlanDTO planDTO = new PlanDTO();
        List<DetailDTO> detailDTOList = new ArrayList<>();
        BeanUtils.copyProperties(plan, planDTO);
        
        QueryWrapper<RepaymentDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.eq("repayment_plan_id", plan.getId());
        List<RepaymentDetail> detailList = repaymentDetailMapper.selectList(detailQueryWrapper);
        for(RepaymentDetail detail : detailList) {
            DetailDTO detailDTO = new DetailDTO();
            BeanUtils.copyProperties(detail, detailDTO);
            detailDTOList.add(detailDTO);
        }

        planDTO.setDetailList(detailDTOList);
        planDTOList.add(planDTO);
    }
    return planDTOList;
}

这样代码直观、简洁,同时还提高了代码的可读性。

是的,可以在同一个QueryWrapper中查询主表和子表,并使用左连接进行关联查询。这样可以避免拆分查询,提高代码的可维护性。修改后的代码如下:

public List<PlanDTO> getPlanDTOList() {
    List<PlanDTO> planDTOList = new ArrayList<>();
    QueryWrapper<RepaymentPlan> planQueryWrapper = new QueryWrapper<>();
    planQueryWrapper.select("t1.id", "t1.consumer_id", "t1.user_no", "t1.project_id", "t1.project_no", "t1.number_of_periods", "t1.interest", "t1.principal", "t1.amount", "t1.should_repayment_date", "t1.repayment_status", "t1.create_date", "t1.commission", "t2.id as detail_id", "t2.repayment_plan_id", "t2.interest as detail_interest", "t2.principal as detail_principal", "t2.amount as detail_amount", "t2.should_repayment_date as detail_should_repayment_date", "t2.repayment_status as detail_repayment_status", "t2.overdue_days as detail_overdue_days", "t2.create_date as detail_create_date")
            .eq("t1.xxx", "xxx")
            .leftJoin("repayment_detail t2 on t1.id = t2.repayment_plan_id");
    List<Map<String, Object>> mapList = repaymentPlanMapper.selectMaps(planQueryWrapper);

    for(Map<String, Object> map : mapList) {
        PlanDTO planDTO = new PlanDTO();
        List<DetailDTO> detailDTOList = new ArrayList<>();
        BeanUtils.populate(planDTO, map);

        DetailDTO detailDTO = new DetailDTO();
        BeanUtils.populate(detailDTO, map);

        detailDTOList.add(detailDTO);

        planDTO.setDetailList(detailDTOList);
        planDTOList.add(planDTO);
    }
    return planDTOList;
}

其中,使用selectMaps()方法返回List<Map<String, Object>>类型的结果,再通过遍历将结果集转为对象。BeanUtils.populate()方法可以将Map中的数据自动赋值给对应的DTO对象,从而避免手动赋值的繁琐。同时,在查询中使用别名将主表和子表的字段进行区分,也有助于提高代码的可读性。

如果您用的是Mybatis Plus,您可以将QueryWrapper中的select方法省略掉,直接用lambda表达式表示要查询的字段,然后使用selectList方法,直接返回List<RepaymentPlan>类型的结果,就像下面这样:

public List<PlanDTO> getPlanDTOList() {
    List<PlanDTO> planDTOList = new ArrayList<>();
    QueryWrapper<RepaymentPlan> planQueryWrapper = new QueryWrapper<>();
    planQueryWrapper.lambda().eq(RepaymentPlan::getXxx, xxx)
        .leftJoin(RepaymentDetail.class, RepaymentPlan::getId, RepaymentDetail::getRepaymentPlanId)
        .select(RepaymentPlan.class, i -> Objects.equals("id", i.getColumn()) || Objects.equals("consumer_id", i.getColumn()) || Objects.equals("user_no", i.getColumn()) || Objects.equals("project_id", i.getColumn()) || Objects.equals("project_no", i.getColumn()) || Objects.equals("number_of_periods", i.getColumn()) || Objects.equals("interest", i.getColumn()) || Objects.equals("principal", i.getColumn()) || Objects.equals("amount", i.getColumn()) || Objects.equals("should_repayment_date", i.getColumn()) || Objects.equals("repayment_status", i.getColumn()) || Objects.equals("create_date", i.getColumn()) || Objects.equals("commission", i.getColumn()))
        .select(RepaymentDetail.class, i -> Objects.equals("id", i.getColumn()) || Objects.equals("repayment_plan_id", i.getColumn()) || Objects.equals("interest", i.getColumn()) || Objects.equals("principal", i.getColumn()) || Objects.equals("amount", i.getColumn()) || Objects.equals("should_repayment_date", i.getColumn()) || Objects.equals("repayment_status", i.getColumn()) || Objects.equals("overdue_days", i.getColumn()) || Objects.equals("create_date", i.getColumn()));
    List<RepaymentPlan> planList = repaymentPlanMapper.selectList(planQueryWrapper);

    for(RepaymentPlan plan: planList) {
        PlanDTO planDTO = new PlanDTO();
        BeanUtils.copyProperties(plan, planDTO);

        List<DetailDTO> detailDTOList = new ArrayList<>();
        List<RepaymentDetail> detailList = plan.getDetailList();

        for(RepaymentDetail detail : detailList) {
            DetailDTO detailDTO = new DetailDTO();
            BeanUtils.copyProperties(detail, detailDTO);
            detailDTOList.add(detailDTO);
        }

        planDTO.setDetailList(detailDTOList);
        planDTOList.add(planDTO);
    }

    return planDTOList;
}

在这个例子中,我们使用lambda表达式表示要查询的字段,然后使用select方法进行选择,从而使代码看起来更加简洁和易于维护。同时,由于Mybatis Plus已经帮我们实现了Bean到Map的转换,我们可以直接使用BeanUtils.copyProperties()方法对对象进行复制,从而避免手动赋值的繁琐。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐