个人BO之导航属性

个人BO
1-个人BO之强类型
2-个人BO之数据保护
3-个人BO之状态控制
4-个人BO之导航属性html

数据须要导航

数据之间广泛存在关系,作业务处理时每每也是按照关系在数据之间查询和处理。业务处理可看做是各类检查和计算后,保存结果。而检查和计算每每意味着要查数据A,以及数据A相关的数据B,数据B相关的数据C……。java

BO 与数据表相对应。一个 BO 类对应一个数据表,一个 BO 对象对应数据表中的一条记录。表间的关系,也是 BO 间的关系。典型的是一对多关系。好比 “买家-订单-订单明细”三者的关系是:一个买家能够拥有多个订单,一个订单对应多个订单明细;反过来,一个订单明细对应一个订单,一个订单对应一个买家。订单是买家的子对象,买家是订单的父对象。数据库

当获得一个订单 BO 时,但愿能够经过它的属性获得它的明细,明细是一个 BO 集合,但愿能够经过它的另外一个属性获得它的买家 BO。同理,当获得一个订单明细 BO,但愿能够经过它的一个属性获得它的订单 BO。缓存

经过 BO 的属性获取到另外一个 BO 或 BO 的集合,这种属性叫作 BO 的导航属性。安全

对null值的处理

当父对象可能为null时,导航到父对象的属性有两个,一个是Xxx,另外一个是XxxOrNull。好比一个学生通常是对应一个班级,但若是业务逻辑容许新生报到时暂未分配到班级,学生的班级属性就可能为null。为了准确地处理null值的问题,学生的班级对应两个属性:ClassClassOrNull。并规定,Class这个属性不返回null,学生当前没有对应班级时,则抛异常,若是但愿返回null而非抛异常,则使用ClassOrNull。当父对象不容许为null时,则不提供XxxOrNull属性。ide

子对象通常表现为父对象的一个集合属性,若一个对象的子对象数量为零,则规定返回空(Empty)集合,而不是nullthis

class 班级Bo extends BoBase {
    public List<学生Bo> get学生List() {
        Long id = this.getId();
        return boProvider.list学生By班级Id(id); // 见说明1
    }
}

class 学生Bo extends BoBase {
    public 班级Bo get班级() {
        Long 班级Id = this.get班级Id();
        return boProvider.get班级(班级Id);
    }
    public 班级Bo get班级OrNull() {
        if (this.get班级Id() == null)
            return null;
        return this.get班级();  // 见说明2
    }
}

说明:设计

  1. boProviderBoBase的属性,一切的 BO 对象都由boProvider产生。
  2. 若是班级Id不是null,却在数据库中找不到该班级数据,则仍是会抛异常,也应该抛异常。
  3. 为了便于说明且不影响道理的表达,这里使用了中文命名,实际项目中并不是如此。

优势

  • 导航属性让使用者方便地获得 BO 对象的相关对象,屏蔽了内部关系的细节,使用方便。
  • 导航属性包含了找不到时返回null仍是抛异常的逻辑,避免了处处编写重复的代码,减小了对null值的处理不当致使空引用异常的风险。
  • 效果:只要获得一个 BO 对象,就能够获得与它相关的所有对象,使业务逻辑代码简洁、安全、灵活。

展望

目前的导航属性是只读的,这点不够面向对象(OO),只是由于实现起来简单。将来如有须要,能够提供修改导航属性同时修改关系的功能,用起来更加OO,可能有一些复杂的技术细节问题要解决。3d

目前经过导航属性获取(BO)对象,每次都从数据库装载,必定几率下会产生多余的查询。解决方法是在内存中统一缓存,经过ID判断若内存已有则不从数据库中取。这个方案一方面会增长一点内存开销,同时为了知足“就算内存中有,也要从数据库装载”的需求,须要设计复杂一点的机制。还须要解决前面的业务修改了的对象,后面的业务(同一个请求)获取是否应该获取修改后的这个对象版本的问题,我目前以为应该获取修改后的版本,而不是数据库中那个。不管获取到的是哪一个版本,会不会在业务处理上形成Bug,有待进一步研究。code

系列导航

1-个人BO之强类型
2-个人BO之数据保护
3-个人BO之状态控制 4-个人BO之导航属性

相关文章
相关标签/搜索