前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java中Vo类的理解

Java中Vo类的理解

作者头像
Tom2Code
发布于 2022-11-21 04:12:04
发布于 2022-11-21 04:12:04
3K00
代码可运行
举报
文章被收录于专栏:TomTom
运行总次数:0
代码可运行

先来解释两个概念

实体类(持久对象)=PO

值对象(新的对象)=VO

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
一、PO:persistant?object?持久对象
可以看成是与数据库中的表相映射的java对象。使用Hibernate来生成PO是不错的选择。

二、VO:value object值对象。
通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象
可以和表对应,也可以不,这根据业务的需要.

有一种观点就是:PO只能用在数据层,VO用在商业逻辑层和表示层。各层操作属于该层自己的数据对象
这样就可以降低各层之间的耦合,便于以后系统的维护和扩展。
如果将PO用在各个层中就相当于我们使用全局变量,我们知道在OO设计非常不赞成使用全局变量。
但是每次都得进行VO-PO的转换,也确实很烦。我觉得有时候也可以在某个商业逻辑或者表示层使用PO
此时在这个商业逻辑的过程中PO的状态是不发生变化的,比如显示一条商品详细信息的商业逻辑。
在开发过的项目中,规模都很小,我一直都把POVO用,因为PO确实很方便,结合Hibernate的DAO
我使用JAVA的集合对象作为值传递的载体,当然Struts也是我的不二之选。
我认为:在一些直观的,简单的,不易发生变化的,不需要涉及多个PO时,传递值还是使用PO好
这样可以减少大量的工作量(也就意味着减少bug,减少风险),也不需要担心未来的维护工作!

vo:value object,值对象
一般在java中用的多的是pojo:plain oriented java object
原始java对象,pojo一般和数据库中的表是一一对应的。
vo一般是来做值的存储与传递。

既然有了实体类与数据库中的字段一一对应了 那为什么还要VO呢

答案是因为在复杂的业务逻辑中,往往单一实体类无法满足我们的需求,就举个简单的例子,一个课程系统中有一级分类和二级分类,那么一个一级分类应该会对应多个二级分类,如果我们使用二级菜单的话,就应该可以实现这种联动的效果,一旦一级菜单确定下来了,那么二级菜单的下拉项中的选项只能是一级菜单下的二级菜单,也许有点绕 发证大意就是需要做到 一对多

一个一级菜单对应多个二级菜单

下面就来一个例子吧,首先有一个在线课堂的项目中有一个分类表

我们先看一下表结构

id就是主键

titie是名称

那么parentId就是上级分类的ID 如果值为0则为一级分类 如果为其他

Springboot中的实体类PO:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.tompro.eduservice.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 课程科目
 * </p>
 *
 * @author testjava
 * @since 2022-07-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="EduSubject对象", description="课程科目")
public class EduSubject implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "课程类别ID")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "类别名称")
    private String title;

    @ApiModelProperty(value = "父ID")
    private String parentId;

    @ApiModelProperty(value = "排序字段")
    private Integer sort;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;


}

但是 正如我在前面说到过的 这种单一实体类 是满足不了我们的需求的

因为例如下图中的需求

我们选中一个一级分类之后 那么下一个下拉列表中的选项只能是 已选中的一节分类下的对应的二级分类

是会有一个联动的反应,所以我们的单一实体类就不能做到了。

这时候,引入我们的Vo类

首先新建一级分类Vo类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.tompro.eduservice.entity.subject;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * 2 * @Author: AkaTom
 * 3 * @Date: 2022/7/12 21:43
 * 4 一级分类
 */
@Data
public class OneSubject {

    private String id;
    private String title;

    //一个一级分类有多个二级分类
    private List<twoSubject> children=new ArrayList<>();

}

然后是二级分类Vo类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.tompro.eduservice.entity.subject;

import lombok.Data;

/**
 * 2 * @Author: AkaTom
 * 3 * @Date: 2022/7/12 21:43
 * 4 二级分类
 */
@Data
public class twoSubject {
    private String id;
    private String title;
}

然后在前端的时候我们则需要获取我们的vo类

vue中的methods:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //点击某个一级分类,触发change,显示对应二级分类
    subjectLevelOneChanged(value) {
      //value就是一级分类id值
      //遍历所有的分类,包含一级和二级
      for(var i=0;i<this.subjectOneList.length;i++) {
        //每个一级分类
        var oneSubject = this.subjectOneList[i]
        //判断:所有一级分类id 和 点击一级分类id是否一样
        if(value === oneSubject.id) {
          //从一级分类获取里面所有的二级分类
          this.subjectTwoList = oneSubject.children
          //把二级分类id值清空
          this.courseInfo.subjectId = ''
        }
      }
    },
    //查询所有的一级分类
    getOneSubject() {
      subject.getSubjectList()
        .then(response => {
          this.subjectOneList = response.data.list
        })
    },

data:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
subjectOneList:[],//一级分类
subjectTwoList:[]//二级分类

页面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 所属分类 TODO -->
      <el-form-item label="课程分类">
        <el-select
          v-model="courseInfo.subjectParentId"
          placeholder="一级分类" @change="subjectLevelOneChanged">

          <el-option
            v-for="subject in subjectOneList"
            :key="subject.id"
            :label="subject.title"
            :value="subject.id"/>

        </el-select>

        <!-- 二级分类 -->
        <el-select v-model="courseInfo.subjectId" placeholder="二级分类">
          <el-option
            v-for="subject in subjectTwoList"
            :key="subject.id"
            :label="subject.title"
            :value="subject.id"/>
        </el-select>
      </el-form-item>

后端service层中的主要方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public List<OneSubject> getAllOneTwoSubject() {
        //1 查询所有1级分类
        QueryWrapper<EduSubject> wrapperOne=new QueryWrapper<>();
        wrapperOne.eq("parent_id","0");
        List<EduSubject> oneSubjectList = baseMapper.selectList(wrapperOne);

        //2 查询所有二级分类
        QueryWrapper<EduSubject> wrapperTwo=new QueryWrapper<>();
        wrapperTwo.ne("parent_id","0");
        List<EduSubject> twoSubjectList = baseMapper.selectList(wrapperTwo);
        //创建list集合 存储最终封装数据
        List<OneSubject> finalSubjectList=new ArrayList<>();
        //封装一级分类
        //查询出来所有的一级分类list集合遍历,得到每个一级分类对象,获取每个以及分类对象值
        //封装到要求的list集合里面
        for (int i = 0; i < oneSubjectList.size(); i++) {
            //得到oneSubject每个对象
            EduSubject eduSubject = oneSubjectList.get(i);
            //把edusubject的值获取出来 放到onesubject中
            OneSubject oneSubject=new OneSubject();
//            oneSubject.setId(eduSubject.getId());
//            oneSubject.setTitle(eduSubject.getTitle());
            BeanUtils.copyProperties(eduSubject,oneSubject);
            finalSubjectList.add(oneSubject);
            // 在一级分类循环遍历查询所有的二级分类
            // 创建list集合封装每一个一级分类的二级分类
            List<twoSubject> twoFinalSubjectList=new ArrayList<>();
            for (int m = 0; m < twoSubjectList.size(); m++) {
                EduSubject eduSubject1=twoSubjectList.get(m);
                if (eduSubject1.getParentId().equals(oneSubject.getId())){
                    //把eduSubject1复制到twosubject中 放到twofinalsubjectlist中
                    twoSubject twosubject=new twoSubject();
                    BeanUtils.copyProperties(eduSubject1,twosubject);
                    twoFinalSubjectList.add(twosubject);
                }
            }
            oneSubject.setChildren(twoFinalSubjectList);
        }
        //封装二级分类
        return finalSubjectList;
    }

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Tom的小院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
springboot实现树形结构的分类显示
我们在开发中都会遇到树形控件,今天就来实现这个功能,我这里这树形结构比较简单,只有二级分类,这里只写出后端实现,前端你只需要把数据拿到赋值给vue的树形控件即可,前端实现方式太简单,这里不做讨论。 我们最终想要的数据结构为:
别团等shy哥发育
2023/02/25
9700
springboot实现树形结构的分类显示
导入Excel数据到数据库
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/115164.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/09
2.5K0
谷粒学院day7——课程管理模块
/views/edu/subject/save.vue写个上传按钮组件。注意下面代码注释,在本地存放模板文件。
半旧518
2022/10/26
5460
谷粒学院day7——课程管理模块
【在线教育】课程科目入门
<groupId>org.springframework.boot</groupId>
陶然同学
2023/02/27
4900
【在线教育】课程科目入门
mybatis之collection实现递归查询级联数据
mybatis之collection实现递归查询级联数据 数据库结构: mbatis mapper文件: <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.xiepanpan.gmall.pms.entity.ProductCategory"> <id column="id" property="id" /> <result column="parent_id" property="parentId
周杰伦本人
2022/10/25
1.1K0
mybatis之collection实现递归查询级联数据
黑马瑞吉外卖之套餐信息的分页查询
首先这里是套餐的功能开发,我们在设置数据库表以及之后的实体类的时候我们需要关注的就是套餐本身的分类以及套餐下关联的菜品。
兰舟千帆
2022/09/29
3620
黑马瑞吉外卖之套餐信息的分页查询
vue实现下拉框二级联动效果
数据格式不一定和上面的一样,我上一篇文章是把这个数据格式用在了树形控件上面,这里放在二级联动上面。
别团等shy哥发育
2023/02/25
3.8K1
vue实现下拉框二级联动效果
MybatisPlus(3)
查询投影是指在查询操作中,只选择需要的字段进行返回,而不是返回整个实体对象。这样可以减少网络传输的数据量,提高查询的效率。
终有救赎
2023/10/16
2590
MybatisPlus(3)
基于SpringCloudalibaba+SSM+Mybatisplus实现在线教育讲师管理后端
基于SpringCloudalibaba+SSM+Mybatisplus实现在线教育讲师管理后端
陶然同学
2023/02/27
5200
基于SpringCloudalibaba+SSM+Mybatisplus实现在线教育讲师管理后端
黑马瑞吉外卖之菜品的分页查询展示(难点)
没有开发分页查询之前,数据是不能正确展示出来的。现在我们就需要实现这儿分页查询的功能。
兰舟千帆
2022/09/27
8840
黑马瑞吉外卖之菜品的分页查询展示(难点)
基于Springboot+MybatisPlus的外卖项目瑞吉外卖Day3
1、在实体类的属性上加入@TableField注解,指定自动填充的策略 2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectMapper接口
小小程序员
2023/03/27
4640
基于Springboot+MybatisPlus的外卖项目瑞吉外卖Day3
【谷粒学院】007-条件查询分页、添加讲师、查询讲师、修改讲师、统一异常处理、统一日志处理
根据讲师名称name,讲师头衔level、讲师入驻时间gmt_create(时间段:开始、结束)查询;
訾博ZiBo
2025/01/06
840
【谷粒学院】007-条件查询分页、添加讲师、查询讲师、修改讲师、统一异常处理、统一日志处理
【MyBatis-Plus】快速精通Mybatis-plus框架—核心功能
刚才的案例中都是以id为条件的简单CRUD,一些复杂条件的SQL语句就要用到一些更高级的功能了。
陶然同学
2023/10/14
1.1K0
【MyBatis-Plus】快速精通Mybatis-plus框架—核心功能
有了这个,SQL语句都不用写了
MyBatis-Puls在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
千羽
2021/01/14
7630
有了这个,SQL语句都不用写了
黑马瑞吉外卖之分类信息的分页查询
在对页面的员工信息处理完之后,我们就开始去处理下一个功能,对分类的功能做一个整体的开发。这是我们的分类管理的界面,现在我们去对界面的分类的展示做一个开发。可以看到是需要进行分页查询,所以我们首先去做一个数据的展示。
兰舟千帆
2022/08/11
3070
黑马瑞吉外卖之分类信息的分页查询
基于Springboot和MybatisPlus的外卖项目 瑞吉外卖Day4
​ **文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上.**文件上传时,对页面的form表单有如下要求:method=“post” enctype=“multipart/form-data” type=“file”
小小程序员
2023/03/27
4870
进阶!MyBatis-Plus(基于 Springboot 演示)
这一篇从一个入门的基本体验介绍,再到对于 CRUD 的一个详细介绍,在介绍过程中将涉及到的一些问题,例如逐渐策略,自动填充,乐观锁等内容说了一下,只选了一些重要的内容,还有一些没提及到,具体可以参考官网,简单的看完,其实会发现,如果遇到单表的 CRUD ,直接用 MP 肯定舒服,如果写多表,还是用 Mybatis 多点,毕竟直接写 SQL 会直观一点,MP 给我的感觉,就是方法封装了很多,还有一些算比较是用的插件,但是可读性会稍微差一点,不过个人有个人的看法哇
BWH_Steven
2020/10/10
6560
MyBatis-Plus的使用
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。
后端码匠
2020/11/06
6530
MyBatis-Plus的使用
基于Springboot和Mybatis的外卖项目 瑞吉外卖Day6
瑞吉外卖Day6 移动端登录功能 一、移动端登录优点及流程 手机验证码登录的优点:方便快捷,无需注册,直接登录 登录流程:输入手机号>获取验证码>输入验证码>点击登录>登录成功 注意:通过手机验证码登录,手机号是区分不同用户的标识。 二、前后端交互流程 在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信 在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求。 三、类和
小小程序员
2023/03/31
6710
关于DO,VO,DTO,QueryParam的思考
DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
benym
2022/07/14
2.9K0
关于DO,VO,DTO,QueryParam的思考
相关推荐
springboot实现树形结构的分类显示
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文