SpringBoot实体类——VO/DTO/PO简单总结

本文介绍了Java后端开发中ViewObject(VO),DataTransferObject(DTO)和PersistantObject(PO)的概念和用途。VO用于前端展示,DTO用于服务层间数据传输,PO对应数据库表。文章详细阐述了它们之间的转换过程,包括使用Spring的BeanUtils和ModelMapper进行对象映射的示例,以及在用户注册和信息查询业务中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.概念叙述

2.类型转换

3.使用实例


1.概念叙述

VO:View Object,主要用于展示层。它的作用是把某个指定前端页面的所有数据封装起来。他的作用主要是减少传输数据量大小和保护数据库隐私数据(如用户密码、用户邮箱等相关信息)不外泄,同时保护数据库的结构不外泄。

DTO:Data Transfer Object,数据传输对象,用于展示层与服务层之间的数据传输对象。(注:实际开发中还存在BO,其作用和DTO类似,当业务逻辑不复杂时一般会被合并。)

PO:Persistant Object,持久化对象,和数据库形成映射关系。简单说PO就是每一个数据库中的数据表,一个字段对应PO中的一个变量。(也就是我们常用的Entities)

几者之间的关系如下图:

从前端页面中收到JSON格式数据,后端接口中将其封装为一个VO对象;接口接收到VO对象后将其转换为DTO对象,并调用业务类方法对其进行处理;然后处理为PO对象,调用Dao接口连接数据库进行数据访问(查询、插入、更新等)。

后端从数据库得到结果后,根据Dao接口将结果映射为PO对象,然后调用业务类方法将其转换为需要的DTO对象,再根据前端页面实际需求,转换为VO对象进行返回。

2.类型转换

上述过程中,VO/DTO/PO等实体类中字段常常会存在多数相同,根据业务需求少数不同。为避免频繁的set和get操作对其进行转换,spring为我们提供了多种方法。

(1)使用BeanUtils:(springframework包下)

UserDto user = new UserDto ();
BeanUtils.copyProperties(userInfo ,user ,new String[]{"birthday"});

上述代码中,意思是将左边UserInfo实体类(可以视为一个VO对象)和UserDto实体类类(可以视为一个DTO对象)中一样的值进行赋值user对象中,new String[]{""}中是跳过赋值的字段,该属性可以为空。

(2)使用BeanUtils:(Apache包下)

UserDto user = new UserDto ();
BeanUtils.copyProperties(user,userInfo);

上述代码中,意思是将右边UserInfo实体类(可以视为一个VO对象)和UserDto实体类类(可以视为一个DTO对象)中一样的值进行赋值user对象中。(和spring包下方法相反)

(3)使用modelMapper:

导入依赖:

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>2.3.9</version>
        </dependency>

配置文件:

@Configuration
public class ModelMapperConfig {

    private Converter<Date, String> dateToStringConverter = new AbstractConverter<Date, String>() {
        @Override
        protected String convert(Date date) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            return date == null ? null : simpleDateFormat.format(date);
        }
    };

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();

        // 官方配置说明: http://modelmapper.org/user-manual/configuration/
        // 完全匹配
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);

        // 匹配策略使用严格模式
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

        modelMapper.addConverter(dateToStringConverter);

        configureUser(modelMapper);

        return modelMapper;
    }

    private void configureUser(ModelMapper modelMapper) {
        //将dto转为UserAccount实体类
        modelMapper.typeMap(UserInfor.class, UserAccount.class)
                .addMappings(mapper -> mapper.map(UserInfor::getUsername, UserAccount::setUsername))
                .addMappings(mapper -> mapper.map(UserInfor::getPassword, UserAccount::setPassword));

}

使用:

UserAccount account= modelMapper.map(userInfo,UserAccount.class);

上述代码,根据配置文件中configureUser方法中配置的字段,将两个实体类中的字段进行复制赋值。

3.使用实例

下面我们模拟一个业务:后端接口从前端中接收到用户注册数据,进行注册;前端调用查询接口,获取用户的数据。

首先,我们定义VO、DTO、PO对象:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo implements Serializable {
    //该实体类为封装好的前端传输页面VO对象
    @NotBlank(message = "用户名不能为空")
    private String Username;
    @NotBlank(message = "密码不能为空")
    private String Password;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO implements Serializable {
    //该实体类为业务处理DTO对象
    private int Account;
    private String Username;
    private String Password;
    private String Roles;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user_account")
public class UserAccount implements Serializable {
    //该实体类为用户账号表对应PO对象
    @TableId
    private int SerialNum;
    private int Account;
    private String Username;
    private String Password;
    private String Roles;
    private String status;
    private String registerDate;
}

然后,我们编写用户注册相关代码(基于springboot+mybatis plus),由于使用mybatis plus,此处省略mapper层代码,仅展示serviceImpl和controller中代码。

控制层:

    //用户注册
    @PostMapping("/register")
    public CommonResult<Object> userRegister(@RequestBody @Valid UserInfo user){
        int result = userService.userRegister(user);
        if(result!=0){
            return CommonResult.success(result);
        }else {
            return CommonResult.fail(result);
        }
    }

业务处理:

    @Override
    public int userRegister(UserInfo user) {
        if(accountMapper.selectCount(new QueryWrapper<UserAccount>().eq("username",user.getUsername()))!=0){
            log.info("用户名已存在");
            return 0;
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userDTO,user);
        //加密密码
        Md5Hash md5Hash = new Md5Hash(userDTO.getPassword(), userDTO.getUsername(),2);
        userDTO.setPassword(md5Hash.toString());
        //模拟生成账号
        userDTO.setAccount(12345678);
        //赋予权限
        userDTO.setRoles("user");
        return accountMapper.insert(userDTO);
    }

最终,我们可以往数据库中传入一条用户刚注册的账号数据,status和RegisterDate等属性取数据库设置好的默认值。

然后,我们再定义一个VO用于展示用户的信息:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVo implements Serializable {
    //该VO用于展示用户信息,去除了用户密码等敏感信息
    private int serialNum;
    private int account;
    private String username;
}

进行用户信息的查询,获取所有的用户账号:

业务层:

    public List<UserAccount> getAllUser() {
        return accountMapper.selectList(null);
    }

控制层:

    @GetMapping("/get/all")
    public CommonResult<Object> getAllAccount() throws InvocationTargetException, IllegalAccessException {
        //查询所有数据
        List<UserAccount> userAccountList = userService.getAllUser();
        List<AdminInfo> resultList = new ArrayList<>();
        //封装为VO进行展示
        for(UserAccount u:userAccountList){
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(userVo,u);
            resultList.add(userVo);
        }
        //根据序列号进行排序,后注册的放在最前面
        resultList.sort(new Comparator<UserVo>() {
            @Override
            public int compare(UserVo o1, UserVo o2) {
                return o2.getSerialNum() - o1.getSerialNum();
            }
        });
        return new CommonResult<>(200,"账号列表如下:",resultList,resultList.size());
    }

然后我们就可查询得到所有的去除了敏感信息可用于展示的用户账号信息。

注:此处由于业务简单,没有将PO对象转换为DTO再转换为VO。

### 回答1: Spring Boot是一个开源的Java框架,用于快速构建基于Spring的应用程序。DTO(Data Transfer Object)是用于在不同层之间传输数据的对象,VO(Value Object)是用于表示值对象的对象,PO(Persistent Object)是用于表示持久化对象的对象,DO(Domain Object)是用于表示领域对象的对象。这些对象在Spring Boot应用程序中经常使用,可以帮助开发人员更好地组织和管理代码。 ### 回答2: SpringBoot是一种非常流行的Java开发框架,它的目标是简化Java应用程序的开发过程。在SpringBoot中,我们通常会用到一些常见的概念,比如DTOVOPO、DO等。 DTO(Data Transfer Object):数据传输对象,是在客户端和服务端进行数据传输的一个数据对象,通常不包含任何业务逻辑,只是一些简单的用于传输数据而已。DTO的作用是将业务数据从持久层传输到逻辑层,再到表示层。在SpringBoot中,DTO模式常用于对数据的基本检查,以避免数据传输错误。 VO(Value Object):值对象,它通常代表业务领域中的一些复合类型,它是一个组合了原始数据成为一个有意义的数据对象,它通常仅提供getter方法以让外部访问其内容。VO的作用是为客户端展示数据提供统一的结构,而且还可以抽象出业务数据内部结构的变化。在SpringBoot中,VO模式通常用于业务实体的展示,对于多个业务实体需要展示的情况下,可以将他们打成一个VO对象,方便统一展示。 PO(Persistent Object):持久对象,它是一个纯数据对象,通常代表数据库中一个表的数据,在SpringBoot中负责持有数据库持久层的数据并对其进行操作。PO模式的作用是表现一个数据对象和数据库中的存储相匹配。在SpringBoot中,PO模式通常用于与数据库的交互,为了避免PO暴露,我们通常要进行一些处理,比如使用Lombok、BeanUtil等。 DO(Domain Object):领域对象,它从业务概念中抽象出来的对象,通常包含了所有与业务相关的数据和逻辑。在SpringBoot中,DO模式通常用于处理与业务逻辑相关的问题,它承载了业务的核心逻辑,同时也是进行业务操作的核心对象。 在实际Java开发中,我们通常会用DTOVOPO、DO等不同的模式来处理各种问题,这些模式可以使我们的代码更加清晰、简明和可维护,提高了代码的可读性和可重用性。当然,模式的使用并不是绝对的,需要基于实际情况来考虑,综合选择最适合的方案。 ### 回答3: SpringBoot是一款快速构建基于Spring框架的应用程序的工具。在实际的开发过程中,我们通常会用到DTOVOPO、DO等代码实体,本文将对这些实体进行详细地介绍。 DTO是Data Transfer Object的缩写,即数据传输对象,一般用于不同服务层之间进行数据传输的载体,可以表示多个数据表的数据信息。DTO通常包含多个数据字段,主要用于在系统各个层之间传递数据信息,它的数据属于只读,适用于业务服务的传输。 VO是Value Object的缩写,即值对象,一般指的是用于在前端展示或接收用户输入时作为数据载体传输的对象。VO的数据属于只读,适用于前端显示和数据传输。 PO是Persistent Object的缩写,即持久性对象,是实体类数据库表之间的映射对象。PO实体类中的属性映射到数据库表中的列,与数据库表一一对应。PO的数据通常是可读可写的,适用于ORM框架实现增删改查的操作。 DO是Domain Object的缩写,即领域对象,是系统中业务实体的对象。DO通常封装了业务逻辑和数据处理的方法,具有完整的业务数据和业务操作能力。DO通常用于业务逻辑处理,数据操作和持久化的实现。 综上,DTOVOPO、DO等实体都是在SpringBoot应用程序开发中常见的代码实体,它们各有其适用范围,能够更好地实现系统的业务逻辑处理,数据传输和持久化等功能。在实际开发过程中,应根据情况灵活运用,提高系统的开发效率和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值