发表于: 2020-06-06 19:17:28

1 1754


    任务三深度思考


    1. 什么是代码生成,mybatis  generator代码生成是怎么实现的,还有什么办法可以生成代码?

    Mybatis generator 生成的文件分两大块,共四种:实体(实体类 pojo.java、条件查询类 pojoExample.java)映射(映射文件 pojoMapper.xml、接口 pojoMapper.java

    MBG 连接数据库后会扫描指定的数据库与表,并且得到他们的所有字段、类型、长度、主键信息来建立实体类。

    其中字段名会按照配置文件的规则进行格式化,MBG 中有一个类型映射表,根据 mysql 中的类型及长度信息转换为 java 的类型。

    其中会遇到一些问题,对于 mysql 中的  int tinyint bigint 来说,长度信息并不会影响他们的存储长度,只会在开启自动填充零的时候对其显示效果产生影响。但是在 MBG 的默认映射表中,tinyint(1) 会转换为 java 中的 boolean。这个时候我们可以通过修改配置文件来改变映射。

     

    example 类中,会生成很多条件查询、排序的方法,主要的作用是对 sql 进行拼接,内部的方法非常多,有针对每一个字段的 or and between noteuals eqals 方法,使用的时候可以根据需求进行自由拼接。

    另外还可以设置排序方式,当然这部分就需要用户来自定义一段 sql 语句了。

     

    其他的自动生成代码方法:

    Velocity 模板引擎快速生成代码

    https://www.ibm.com/developerworks/cn/java/j-lo-velocity1/index.html

    FreeMarker

    http://freemarker.foofun.cn/index.html

     

     

    2.Mysql 的一般而言应该配置多大的内存, 多大的硬盘 ,多大的连接数?

    一般来说 Mysql   的内存设置应该尽量接近物理机的内存,但又要给其他的服务与系统留下足够的内存空间。

    Mysql 内存占用计算器:http://www.mysqlcalculator.com/

    详解:

    key_buffer_size决定了  myisam 索引块缓存区的大小,影响着 myisam 表的存取效率。一般来说应该把 1/4 的可用内存分配给 key_buffer_size

    query_cache_size:作用于 select 语句,对其结果集做了缓存,所以不适用于那些更新频繁的表。

    innodb_buffer_pool_size:定义了 InnoDB 存储引擎的表数据和索引数据的最大内存缓冲区,可以缓存数据块与索引键。

    max_connections:允许的同时客户数量,应该尽量调整为更大的值,否则将会经常出现 too many connections

     

    3.在端到端的请求当中,建立Http连接需要多久,Model通过JSP转成Json需要多久,Nginx调用Resin需要多久,Service访问DB需要多久,一个Sql语句执行的时间是多久。

    使用 curl -w 参数可以获取连接建立过程中各部分所占用的时间,以修真院的官网为例,命令如下:

    其中  curl-format.txt 内容如下:

         time_namelookup:  %{time_namelookup}\n
             time_connect:  %
    {time_connect}\n
          time_appconnect:  %
    {time_appconnect}\n
            time_redirect:  %
    {time_redirect}\n
         time_pretransfer:  %
    {time_pretransfer}\n
       time_starttransfer:  %
    {time_starttransfer}\n
                          ----------\n
               time_total:  %
    {time_total}\n

     

    • time_namelookup:DNS       域名解析的时候,就是把 https://zhihu.com 转换成       ip 地址的过程
    • time_connect:TCP       连接建立的时间,就是三次握手的时间
    • time_appconnect:SSL/SSH       等上层协议建立连接的时间,比如 connect/handshake 的时间
    • time_redirect:从开始到最后一个请求事务的时间
    • time_pretransfer:从请求开始到响应开始传输的时间
    • time_starttransfer:从请求开始到第一个字节将要传输的时间
    • time_total:这次请求花费的全部时间

     

    来自 <https://cizixs.com/2017/04/11/use-curl-to-analyze-request/>

     

    可以算出修真院官网的 DNS 查询时间:17 ms

    TCP 连接时间:157-17=140  ms

    服务器处理时间:193-157=26 ms

    内容传输时间:接近 0 ms

    model通过jspjson怎么算时间我真的没想出来,直接 return modelandview,之后就是渲染都不知道去哪里插入时间戳。

     

    4.什么是Sql注入,应该怎么解决?对于未做SQL注入防范的程序,你可以直接通过调用接口删掉表吗?

    用户通过一些特殊的字符串输入使得我们预定义的 sql 语句的语义发生了变化,严重的时候可能会对数据造成损伤。

    解决方法有多种:

    a,通过替换的方式把我们知道的可能会造成 sql 注入的特殊字符剔除掉

    b,不要给应用服务器过高的数据库权限

    c,使用预编译的 sql 语句,可以完全避免 sql 注入

     

    5.在内存里拼装数据会节省时间吗?如果不能,为什么要选择单表查询,而不是直接拼装成Sql语句。

    不懂这个【内存里拼接数据】是指什么。我理解为多个单表查询(即多个单表数据载入内存后处理得到所需数据)是否比逻辑写入 sql 中由 mysql 直接返回所需数据快。

    我觉得还是在 mysql 中直接处理更快,毕竟没有了数传输的耗时。

    【为什么选择单表查询,而不是直接拼接成 sql 】我理解为为什么不用 join 或者其他的多表查询方式?

    a,不利于写操作,join 执行读操作就会同时锁住多张表,影响其他业务的几率提升了很多。

    b,不利于维护,如果其中有表发生了变化(分表),那么需要重写 sql,这个时候多表查询语句的改动可能比较繁琐。

     

     

    6.为什么一般而言,不允许使用连表查询,不允许使用复杂的Group By等语句,为什么不允许使用存储过程?

    优点:

    a,简化了代码逻辑

    b,减少了不必要的数据传输,毕竟查询完很多数据都是不需要的

     

    缺点:

    a,数据表如果由修改那么连表查询就需要做修改,工作量未知

    b,连表查询会锁表,不利于写操作

    csql 中可能会有复杂的嵌套,写完就忘

     

    7.为什么响应时间一般不允许超过200MS,怎么查看一个请求从发起到结束,耗费在什么地方了?

    查看 access log,或者自己去关键节点打日志。

    第三个问题写了用 curl 来获取建立连接的耗时。

    200ms 以内的响应用户体验会比较好吧。

     

    8.为什么要自测,仅仅使用Postman来测试足够吗?什么是本地测试,什么是在开发环境测试?在开发过程中,应该每天部署代码到开发环境吗,为什么?

    为什么要自测?因为很多问题在开发阶段就要解决掉,避免给其他人(比如前端)的工作造成困扰。

    只用 postman 应该还是不够的,但是目前能满足我的需求。

    本地测试:在自己的电脑上启动项目测试,好处是快。

    开发环境测试:模拟真实的运行环境进行的测试。

    还是应该每天一部署,方便测试,及时发现问题。

     

    9.保存图片有几种方式?什么样的情景下应该使用哪一种?

    还没做过图片保存,不过看到有用 MultipartFileMultipartHttpServletRequest 做图片保存的。

     

    10.为什么要先写单元测试?单元测试应该包括哪些?在正式打包的过程中,什么样的单元测试应该被屏蔽?在Maven里用什么方法可以跳过单元测试,单元测试应该被跳过吗。

    在我的学习过程中都是先实现再测试,完全是因为一些方法没有定下来,没法先写测试。我想这也是我今后要努力的方向,项目做好拆分,写好测试单元最后实现。

    涉及数据库的写入、删除、更改的测试用力必须要屏蔽掉,我打包都是跳过所有的单元测试编译,主要是部署的数据库与本地的不一致,就算打包进去了测试也通不过。

    Maven 跳过单元测试打包的方法:

    a,修改 pom 文件

    <build> 

        <plugins> 

          <plugin> 

             <groupId>org.apache.maven.plugins</groupId> 

             <artifactId>maven-surefire-plugin</artifactId> 

             <version>2.18.1</version> 

            <configuration> 

               <skipTests>true</skipTests> 

            </configuration> 

          </plugin> 

        </plugins> 

     </build> 

    b,打包的时候带参数

    mvn  clean install -Dmaven.test.skip=true

     

    11.为什么提供假数据的时候要求,直接Controller接收请求,在JSP中写死数据返回以用做假数据?为什么提供假数据的时候要求数据完整,有分页尽可能给分页,数据尽可能真实?

    因为刚开始开发可能数据库都没有,更别说实体类了,要么用 map list 什么的自己堆一个数据返回,要么用 jsp 写死,我肯定选择用 jsp,用起来非常方便快捷。

    一个 controller 加若干 jsp 就能返回假数据,看起来直观,修改起来也方便。

     

    12.为什么要写假数据,前后端联调的时候,应该什么时候商定接口文档,接口文档应该谁来维护,如果不提供假数据,会发生什么问题?

    开始项目的时候就要一起定好接口文档。

    维护应该还是要由后端来吧。

    不提供假数据前端不好调试。

     

    13.接口应该怎么定义?一个页面应该只对应一个接口吗?还是一个实体对应一个接口,让前端去组装数据?两者的使用场景是什么?

    遵从 rest 风格。一个页面可以多个接口,也不应该就是一个实体对应一个接口,接口应该根据业务的需求来确定,毕竟软件即服务。

     

    14.多层分类应该怎么设计表结构,分别有什么问题?像文章分类这种需求,如果分类不确定,级别不确定,有可能动态调整,数据量和访问量又比较大,该怎么去设计?

    任务三就遇到了这个问题,最终我采用了这样的设计:

    效果如下:

     

    子分类带上父分类的 id,这样分再多层也没有问题,实际使用的时候应该不会超过5层吧。

     

    15.什么是实体表,什么是关系表,一对多和多对多应该怎么设计表?

    实体表即对应实体类,可以被实例化。关系表即存储表之间的关联、映射,不被实例化。

    一对多:一张表就够了,比如一个学校里有多个学生

    一对一:一个人只有一个身份证号码

    多对一:多个学生在同一个班级,这时可以加一张关系表,更简单的是学生表加一个班级字段。

    多对多:一个班级有多个学生,每个学生都可以选择多个课程。可以拆分为多个映射表。

     

    16.什么是外键,用处是什么,为什么不建议使用外键做关联?

    外键:两个表,一个主表,一个从表,主表的主键,放到从表的表格内,然后这个从表和主表就通过外键关联了,这个从表的这个一列和主键有关系的数据,就是从表的外键。目的是控制存储在外键表中的数据,使两张表形成关联。

    优点:

    a,保障数据的完整性

    b,使用数据库的外键约束程序的行为(这条数据不能删,因为他在从表中还有数据)

    缺点:性能差

     

    我感觉可以中和一下,开发与测试的时候数据库设置外键但是不用,纯用于约束不规范的业务逻辑,上线的时候不用就好了。

     

    17.什么是数据库范式,是否应该严格遵守范式,什么情况下应该不遵守范式?

    数据库范式:看了一下百度百科没看懂··· 知乎上有个回答能让我懂点味道,这里贴一下:

    如何理解关系型数据库的常见设计范式?  - 刘慰的回答 - 知乎

    https://www.zhihu.com/question/24696366/answer/29189700

     

    遵从范式的好处是冗余数据会很少,节约了存储空间,增删改查的时候能够确认数据数是唯一的,只需要对一处做修改。



返回列表 返回列表
评论

    分享到