Po类设计
0、承接MySQL 表设计,同样地,这篇博客中一部分内容是Deolin的个人观点和习惯。
1、一般Po类的域是和DB表字段一一对应的,
而由于每个信息表和关联表都有id、insert_time、update_time、remove_time字段,
所以可以提取一个PoCommon类供具体的Po类继承
abstract public class PoCommon {
    private Integer id;
    private Date insert_time;
    private Date update_time;
    private Date remove_time;
    // getters ,setters and toString here
}
class StudentPo extends PoCommon {
    private String name;
    // getters, setters and toString here
}
2、插入行为中,每个Po类都会指定insert_time, del_flag
修改行为中,每个Po类都会指定update_time
移除行为中,每个Po类都会指定del_flag
所以可以追加三个静态工厂方法
    public static <T extends PoCommon> T forInsert(Class<T> clazz) {
        T po;
        try {
            po = clazz.newInstance();
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
        // id是自增的
        po.setInsert_time(new Date());
        return po;
    }
    public static <T extends PoCommon> T forUpdate(Class<T> clazz, Integer id) {
        T po;
        try {
            po = clazz.newInstance();
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
        po.setId(id);
        po.setUpdate_time(new Date());
        return po;
    }
    public static <T extends PoCommon> T forRemove(Class<T> clazz, Integer id) {
        T po;
        try {
            po = clazz.newInstance();
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
        po.setId(id);
        po.setRemove_time(new Date());
        return po;
    }
业务层获得了具体表的Po对象以后,就可以往里面set业务上的数据了。
StudentPo po = PoCommon.forInsert(Student.class);
po.setName("Deolin");
3、增/改/移除操作因为是原子操作,可以用Po类,
而查表操作用Po类则不太适合。
因为,对于业务层而言,查到insert_time, update_time, remove_time是没有意义的
这样的操作需要自定义的持久层对象(Cpo,custom persistence object)(为了类名短一点,Deolin定的缩写...)
class StudentCpo {
    private Integer id;
    private String name;
    // getters, setters and toString() here
}
可以Cpo不再继承与PoCommon,id域被放入了自己的内部,也不需要静态工厂方法了,因为Mybatis框架会把结果集的字段名注入到Cpo对象中。
4、查表操作有时为了不多次查表,所以会出现一些多表查询,主要是两个数据实体一连结一情况,
这种情况更加需要使用Cpo类
SELECT person.id, person.name, student.grade as student_grade, school_address
FROM person, student, school
WHERE person.id = student.id
AND person.remove_time IS NULL
AND student.remove_time IS NULL
class PersonCpo {
    private String id;
    private String name;
    private String student_grade;
    // getters, setters and toString here
}
由于业务上child只是与person一一对应的拓展表,结果集的主体还是person,所以选择了PersonCpo作为命名。
5、至于多表查询中两个数据实体一连结多的情况,则需要两个Cpo了
SELECT school.id, school.name,
student.name AS one_student_name, student.age AS one_student_age
FROM school, student
WHERE school.id=10086
AND student.for_school=school.id
AND school.remove_time IS NULL
AND student.remove_time IS NULL
这个需求是查出10086号学校的校名,和每一个学生的名字、年龄(假设这里学生表有name和age字段了),
那么两个Cpo可以这么定义
public class StudentCpo {
    private String one_student_name;
    private Integer one_student_age;
    // getters, setters, toString here  
}
public class SchoolCpo {
    private Integer id;
    private String name;
    private List<StudentCpo> studentCpos;
    // getters, setters, toString here  
}
首先,如果还像4、那样定义一个有学生信息的school是不合适的,因为这里会有很多学生,会产生很多schoolCpo,
那么schoolCpo里面的域[id]和域[name]等于产生了很多份,造成了毫无必要的内存浪费,
所以在schoolCpo设计了一个List类型的域,这样一来schoolCpo对象只有一个,域[id]和域[name]只有一份。
指的注意的是,这样的设计需要在statement的<select>标签上指定resultMap属性,并在用上<collection>标签
但是这样设计可能有一些无法避免的问题,
只要在持久层存在一个SQL比较独特的statement,
那就需要专门写一个Cpo为它服务(如果是一连结多的话,需要至少2个Cpo),
这些Cpo是很难为其他statement复用的,一旦那个SQL文SELECT后面的东西改了,这些Cpo也得跟着改。
实际上问题的根源在于为什么会出现这样这样statement,
业务层完全可以调用2个statement,第一个取学校信息,映射到学校Cpo(只去除3个time的Cpo复用性还是很高的),
第二个取学生信息,映射到学生Cpo的List,分别调用完之后转换一个Map<String, Object>就可以返回给控制层了。
这样做的缺点,是会有两次数据库请求,可能是出于性能的考虑,业务层才会需要独特的SQL。
以上便是出现复杂的查表需求时,持久层可以采取的两个方法,总结一下
Mapper中声明一个特殊的statement,为这个statement专门写几个Cpo,优点是一次查表,而且业务层代码精炼,持久层的返回值可以直接向上返回;缺点是Cpo们和statement耦合了。
Mapper中声明若干个statement拆分简化需求,用复用性号的Cpo作为结果对象,优缺点跟上一条相反
Po类设计的更多相关文章
- Maven插件mybatis-generator,如何让生成的PO类的field上有对应表字段的注释
		前言 去年刚入职的时候,我就发现,po类(和数据库表对应的类)上,一片都是光秃秃的,什么注释都没有,类上没注释,field上也没注释. 在以前的项目中,其实我们都是有生成注释的,比如,对于下面这个表: ... 
- iOS控制器之基类设计
		题记 在进入新公司后.经过这一个月的重构项目,终于把项目做到了个人相对满意的程度(还有一种不满意的叫老板的需求,提过多次意见也没用= =!).在这次重构中按照以前的思路设计出了个人觉得比较适用的一个基 ... 
- 水果项目第1集-想法>需求->功能->数据库设计->类设计
		懒,懒人,我是个懒人. 懒人想做点事,总是拖拖拉拉,迟迟没有开始. 很久很久以前,就想做属于自己的产品,但是至今还没有一个属于自己的产品. 两年前,终于想好,要做一个网上卖水果的系统,手机上点点,水果 ... 
- [theWord] 一种英文字典的基类设计
		theWord --- 一种英文字典的基类设计 使用场景 想写一个应用,来记录自己背单词时候,对每个单词的记忆状况之类的东西.至于为什么做这个,试过了一些背单词软件,并不觉得好用,自己做一个吧. 那么 ... 
- 利用MyEclipse自动创建PO类、hbm文件(映射文件)、DAO
		原文地址:http://blog.csdn.net/fangzhibin4712/article/details/7179414 前提条件:表sjzdfl 表sjzdxx (使用数据库MySQL) ... 
- YTU 2602: 熟悉题型——类设计( 矩形类定义【C++】)
		2602: 熟悉题型--类设计( 矩形类定义[C++]) 时间限制: 1 Sec 内存限制: 128 MB 提交: 183 解决: 119 题目描述 定义一个矩形类,数据成员包括左下角和右上角坐标 ... 
- Java 类设计技巧
		摘自<Java核心技术>卷I:基础知识 p140 第4章对象与类 - 类设计技巧 1)一定将数据设计为私有. 最重要的是:绝对不要破坏封装性.有时候,需要编写一个访问器方法或更改器方法,但 ... 
- 字体图标,盒子显隐,overflow属性,伪类设计边框,盒子阴影2d形变
		字体图标 ''' fa框架: http://fontawesome.dashgame.com/ 下载 => 引入css文件 引入字体图标库 <link rel="styleshe ... 
- Java11-java基础语法(十)类设计综合案例
		Java11-java语法基础(十)类设计综合案例 一.类综合设计方法 1.类设计步骤 (1)分析数据成员 (2)分析成员方法和构造方法 (3)画出类图 (4)编码测试 2.具体问题 1)分析数据成员 ... 
随机推荐
- 本地虚拟机NAT模式下怎么设置才可以访问外网
			记:因为我要在本机虚拟机上安装Docker,结果发现虚拟机环境不能上网,是主机模式.我要调成net模式下才可以访问外网,这就需要怎么设置.下面文章记录一下. 在本机安装VMware软件后,系统中会自动 ... 
- Python练习_数据类型_day5
			1. 1.作业 1,有如下变量(tu是个元祖),请实现要求的功能 tu = ("alex", [11, 22, {"k1": 'v1', "k2&qu ... 
- 媲美pandas的数据分析工具包Datatable
			1 前言 data.table 是 R 中一个非常通用和高性能的包,使用简单.方便而且速度快,在 R 语言社区非常受欢迎,每个月的下载量超过 40 万,有近 650 个 CRAN 和 Biocondu ... 
- springboot mvc自动配置(二)注册DispatcherServlet到ServletContext
			所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 上一篇文章中,我们看到了DispatcherServlet和DispatcherServ ... 
- h5获取地理坐标
			h5获取地理坐标 方法:h5自带获取地理信息的api api:navigator.geolocation.getCurrentPosition https://developer.mozilla.or ... 
- django 常用 详解
			Django 1 django框架介绍 是一个开源框架,2005年发布,采用Python语言编写的,早期时主要做新闻和内容管理的网站 Django本身提供了非常强大的后台管理系统 看中文说明文档 百度 ... 
- Kubernetes的核心技术概念和API对象
			Kubernetes的核心技术概念和API对象 API对象是K8s集群中的管理操作单元.K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作.例如副本集 ... 
- keepalived+lvs+usp安装实施文档
			操作系统平台:RedHat6.4 x86_64 软件:LVS+keepalived LVS+Keepalived 介绍 LVS LVS是Linux Virtual Server的简写,意即Linux ... 
- RT-Thread--时间管理
			时钟节拍 时钟节拍是特定的周期中断,可以看是系统心跳,中断之间的时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间. ... 
- Centos7下安装MongoDB4.0.10
			前言 模式自由 :可以把不同结构的文档存储在同一个数据库里 面向集合的存储:适合存储 JSON风格文件的形式 完整的索引支持:对任何属性可索引 复制和高可用性:支持服务器之间的数据复制,支持主-从模式 ... 
