相对的一对多和多对一,一对一的分表概念

栏目: Java · 发布时间: 6年前

内容简介:最近公司在做这样的一个业务,由我来设计数据库,其中有有一个需求,根据原型图设计数据库吗,这也是我第一次独立设计数据库,因涉及公司的机密,只能展示部分原型图:1、如图是项目的原型图,每个项目都是一条记录,因而,这可以设计成独立的项目表

导读

最近公司在做这样的一个业务,由我来设计数据库,其中有有一个需求,根据原型图设计数据库吗,这也是我第一次独立设计数据库,因涉及公司的机密,只能展示部分原型图:

1、如图是项目的原型图,每个项目都是一条记录,因而,这可以设计成独立的项目表

相对的一对多和多对一,一对一的分表概念

2、当点击红框中的“人员”,就会出现一个弹框,弹框如图所示。

相对的一对多和多对一,一对一的分表概念

这是项目人员,自然是根据项目来的。不同项目可能有不懂的人员。因而,这可以设计成一张项目人员表。表中的字段肯定有 “人员类型” ,比如业务员,业务部经理等。外键自然是项目的主键。一个项目可能会有多条记录,比如说业务员一条记录,业务部经理一条记录等。所以,对于项目而言,这是一对多的关系,是什么意思呢?一个项目在项目人员表有多条记录;但对于项目人员来说,这是多对一的关系,多条项目人员的记录对着一个项目。如图所示:

相对的一对多和多对一,一对一的分表概念

生成数据表结构是有 Java 代码生成的,因而,代码如下:

/**
 * Created By zby on 15:00 2018/12/25
 * 项目人员
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table(name = "zq_project_person")
public class ProjectPerson extends BaseObj {

    /**
     * 人员类型
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "person_type")
    private PersonTypeEnum personType;

    /**
     * 人员的ids,存储人员的编号
     */
    @Column(name = "ids")
    private String ids;

    /**
     * 选择时间
     */
    @Column(name = "op_time")
    private Date opTime;

    /**
     * 项目
     */
    @ManyToOne
    @JoinColumn(name = "project_id")
    private Project project;

}

人员类型是枚举,代码如下:

/**
 * Created By zby on 9:43 2018/12/27
 */
public enum PersonTypeEnum implements TitleEnum {
    PERSON_TYPE_SALESMAN("业务员"),
    PERSON_TYPE_SALESMAN_MANAGER("业务部经理"),
    PERSON_TYPE_DESIGNER("设计师"),
    PERSON_TYPE_DESIGNER_MANAGER("设计部经理"),
    PERSON_TYPE_PROJECT_SUPERVISION("工程监理"),
    PERSON_TYPE_ENGINEERING_MANAGER("工程部经理");

    。。。

一对多和多对一

一和多的概念

通过以上的分析,我们知道一对多和多对一的关系。这个 “一” “多” 到底是什么是 “一”,什么又是“多”呢?在实际的项目中,我们多问几个为什么,成长也会特别的快。不要怕问,也许,人家可能没时间回答你,或许,人家害怕把你教会了。这样,也要问,不问就永远不知道。

“一”针对“一个点”来说,就像是spring中的aop(Aspect Oriented Programming)编程一样。spring框本身就是以算法驱动为开发,但我们在使用它时,一般是以业务驱动为开发的。既然是业务处理,自然涉及到业务的诸多流程,比如,专门将JVM中的瞬时态的对象转化为数据库的持久态的字段值、或将数据库的持久态的字段值转化为顺势态的Java对象的dao(data access object)层;专门处理数据库事务相关的事务层(service层);专门处理接受前端数据和返回前端数据的控制层(controller层)。

我们单单只考虑其中的一个业务流程,即数据库的事务层(service层)。这就是一个点,也就是aop需要考虑的一个点。aop的配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd"
       default-lazy-init="true">

    <!-- =================================================================== -->
    <!-- AOP: Configuration and Aspects    @TODO:事务缩小范围到 固定的 名字                                  -->
      <!-- 采用 ant风格的编写方式, 一个 * 表示至少有0个字母,两个 ** 表示至少有0个目录                        -->
    <!-- =================================================================== -->
    <aop:config>
        <aop:advisor id="managerTxOne" advice-ref="txAdvice" pointcut="execution(* *..service.*Service.*(..))"
                     order="0"/>
    </aop:config>

    <tx:annotation-driven/>

    <!-- 开启AOP监听 只对当前配置文件有效 -->
    <aop:aspectj-autoproxy expose-proxy="true"/>

    <tx:advice id="txAdvice">
        <tx:attributes>
            <!--获得单个对象-->
            <tx:method name="get*" read-only="true"/>
            <!--列表对象-->
            <tx:method name="list*" read-only="true"/>
            <!--搜索分页对象-->
            <tx:method name="search*" read-only="true"/>

            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    
</beans>

我们注意上面的<aop:config> 。。。</aop:config>这段代码,其实就是配置的设置这个点。这个是处理所有以service结尾的。

因而,回头说说我们数据的库的 “一” ,这是针对一条记录来说的,比如上文说到的项目表中有很多项目,我们单单举出来编号为167的项目,那么,这就是 “一” “多” 我们针对的是当前数据表中涉及到外键字段的记录的条数。比如在项目人员表中,外键名为project_id的项目编号等于167的有很多条记录。那么,这就是 “多”

一对多和多对一的理论示例

所以,一和多之间,并非绝对的关系,只是相对来说。就像我们初中学过的运动间的相对关系。什么是静止的,什么是运动的?我们坐在车厢里,相对于窗外的行道树,我们是运动的。相对于车子,我们就是静止的。所以,也有句话,叫做日行不动八万里。万物就是这样,没有绝对的关系。因而,在实际的项目中,我们遇到了太多的一对多(多对一)的关系,比如:

  1. 项目和项目人员就是一个典型的一对多和多对一的关系。因为上文提到了,就不再赘述。
  2. 项目和项目阶段也是一对多和多对一的关系。一个项目从执行到竣工,肯定有很多的阶段,每个阶段的执行时间、阶段名称、涉及到的人等。因而,这也是一对多的关系。所以,在项目阶段表中相同项目编号的记录至少零条。
  3. 评论表和用户、文章也是一对多和多对一的关系。比如我在思否写了篇文章,当其他用户登录了,假设评论我的文章,一个用户可以评论多次一篇文章,一个用户也可以评论我的多篇文章。所以,在评论表中,一个用户的记录至少零条,一个用户的文章的记录数至少零条。
  4. 同一张表中也可以存在一对多的关系。如文章类型这张表,文章类型肯定有父类型。在这张表中,父类型至少有零条记录数。如栏目,栏目肯定有父类型,父栏目下面有子栏目,父栏目的记录至少有零条。
  5. 根据4所说的,一个文章类型下面有多篇文章,这也是典型的一对多;一个栏目下面有多个内容,这也是典型的一对多。
  6. 。。。在有的话,欢迎评论。

以项目人员为示例

相对的一对多和多对一,一对一的分表概念

业务需求

我们只有点击选择人员,才将数据保存到数据库中,但是,我们还是要将人员类型按照顺序展示出来。因而,我们需要考虑的是,判断数据库中是否存在某种人员类型,比如业务员类型,业务部经理类型。

  • 存在,就把数据表的对象取出来,然后填充到集合容器中。
  • 不存在,我们就要不存在人员类型填充到集合容器中。

算法思想:

在做项目之前,我们需要考虑算法,否则,做出来的东西虽然没错,但不是业务所需要的。

  1. 我们从数据库中取出当前项目下的项目人员的记录,即 List<ProjectPerson> projectList = projectPersonDao.listProjectPersons(projectId);
  2. 我们获取枚举对象的数组,然后遍历枚举集合,即 for (PersonTypeEnum obj : PersonTypeEnum.class.getEnumConstants());
  3. 设置一个开关,true 表示数据存在该枚举对象,false 表示数据库不存在该枚举对象,即 boolean objInProjectPerson = false;
  4. 再遍历projectList ,获取项目人员的对象,拿到人员类型的对象,与枚举对象进行比较,如果相等,就objInProjectPerson置为true,然后挑出内循环。
  5. 判断objInProjectPerson状态,如果未false,就将人员类型的对象设置为当前枚举对象。
  6. 最后,通过 projectPersonList.sort(Comparator<? super E> c)方法进行排序。因为方法形参的是Comparator接口,因而,我们需要一方法内部类的方式实现排序。

方法实现

通过上文的算法设计,我们编写实现方法:

@Override
    public Result<List<ProjectPerson>> listProjectPersons(Long projectId) {
//        【1】步骤一
        List<ProjectPerson> projectList = projectPersonDao.listProjectPersons(projectId);
        List<ProjectPerson> projectPersonList = new ArrayList<>();
        Class<PersonTypeEnum> clz = PersonTypeEnum.class;
        //        【2】步骤二
        for (PersonTypeEnum obj : clz.getEnumConstants()) {
            //        【3】步骤三
            boolean objInProjectPerson = false;
            for (ProjectPerson projectPerson : projectList) {
                //        【4】步骤四
                if (obj.equals(projectPerson.getPersonType())) {
                    projectPerson.setSort(obj.ordinal());
                    objInProjectPerson = true;
                    projectPersonList.add(projectPerson);
                    break;
                }
            }
            //        【5】步骤五
            if (!objInProjectPerson) {
                ProjectPerson projectPerson = new ProjectPerson();
                projectPerson.setPersonType(obj);
                projectPerson.setSort(obj.ordinal());
                projectPersonList.add(projectPerson);
            }
        }
        //        【6】步骤6
        projectPersonList.sort(new Comparator<ProjectPerson>() {
            @Override
            public int compare(ProjectPerson firstProjectPerson, ProjectPerson secondProjectPerson) {
                return firstProjectPerson.getSort() - secondProjectPerson.getSort();
            }
        });
        return ResultUtil.buildSuccess(projectPersonList);
    }

总结

我们在开发过程中和,要分明白何时以业务驱动为开发对象,何时以算法驱动为开发对象。这样,做一个有条理的人,你就会获得更多的知识。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Out of Control

Out of Control

Kevin Kelly / Basic Books / 1995-4-14 / USD 22.95

Out of Control is a summary of what we know about self-sustaining systems, both living ones such as a tropical wetland, or an artificial one, such as a computer simulation of our planet. The last chap......一起来看看 《Out of Control》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具