【项目实战】 图书信息管理系统(Maven,mybatis)(第一个自己独立完成的项目3)

简介: 【项目实战】 图书信息管理系统(Maven,mybatis)(第一个自己独立完成的项目)

八、调试过程中的主要问题、难点以及解决过程


实话说,在调试的过程中我遇到了很多问题,也查阅了很多技术博客,这之中有些确实能解决问题,而有些则是查阅了很多博客,尝试了很多方法还是没能解决问题,或者说出现了另一个问题,对此,我也渐渐摸索出了一套查找解决bug的方法,收获还是蛮大的。


以下列举了我调试中的几个主要问题和解决过程。


1.如何组织各个模块?

我一开始是采用递归循环的方式,但仔细一想,不对!经过我不断调试改进,最终用"套娃"的方式解决了问题,详细思路可以回到 第五部分、主要功能模块的算法流程图 去查看。

2.如何让整个项目有条不紊,井然有序?

整个项目累计代码总量超过千行,如果代码之间逻辑不清晰,关系复杂,那么这个项目调试,后期维护将变得举步维艰。


那么如何做到有条不紊,井然有序呢?


首先要做到项目结构清晰,可以像下面这样,实体类和实体类放在一起,工具类单独放在一起,资源配置文件放在一起,做到项目结构条理清晰。

q4.png

其次,要做到代码封装抽象,具体做法就是把复用性高的代码抽离出来,封装成一个工具类,比如我要每个模块都有打印图书信息结果的需求,那么我们完全可以把它封装起来,比如这里我就把它封装成Displayer工具类,其内部有两个方法,如下图:

q3.png

可以看到Displayer类有两个方法,但方法名其实都是show,只是针对不同情况进行重载,让方法用起来更加方便。这里还有个小细节,就是方法都是采用静态的方式,因为这里并没有要初始化的数据,所以采用静态,这样可以让代码调用的时候并不需要实例化即可调用其内的方法,让工具类使用起来就更加方便。

3.Maven项目,Mybatis框架,IDEA 的坑

q2.png


上图是我在调试遇到的一个问题,可以看到程序报了Mapped Statements collection does not contain value for xxx的异常,这很明显是mybatis框架报的异常,通过报错信息大概猜测是mybatis XXX容器内不包含我写的Mapper(因为那时候我还不知道Mapped Statement是什么东西),然后我就无脑将这段报错信息贴到百度上搜,确实有很多博客记录了此错误及解决方法,我截了一个下来,如图:


q1.png


但实际上我按照博客上一个个去做,并没有解决问题,这时候我已经花了一个下午时间去查找,问题没解决,倒是把mybatis框架复习了一遍。


苦思之下,我开始逐步调试,以下是我的思考过程:


因为问题肯定出在mybatis框架上,所以我逐步调试,但是呢,我又不懂mybatis源码,看得云里雾里。不过我之前自学Java的时候,跟着视频写过一个类似mybatis的框架------SORM框架(不过功能肯定没mybatis框架复杂,是个小型版的框架),做完后学了其他知识后,自己又回头帮它迭代优化了一下,增加了新的功能,优化了结构。


去.png


这段经历让我能大概理解mybatis框架的一些行为,比如在这个地方我就注意到了mappedStatement对象size为0。这时我就猜测这应该是框架本身并没有读取到我写的sql语句,那是由什么造成的呢?



去.png

这时候我就开始测试,不用接口类的方式(因为创建实体类也是mybatis框架底层做的),为了缩小问题的范围,我们采用原始的方式(但不是原生jdbc),发现还是这个错误,然后我开始怀疑mapper注册问题



w3.png

这里我原本是采用包扫描的方式注册,然后我开始尝试用指定路径文件方式去注册


w2.png


然后异常变了,说找不到这个文件


好家伙,之前包扫描的时候报的是Mapped Statements collection does not contain value for xxx,现在直接报没找到这个文件!


这时候我就开始思考为什么?


为什么我用包扫描的方式就不报错呢?而用具体的文件路径就报错呢?


真的是包扫描时找到了xml文件而具体文件路径没找到吗?


不对,不是这样的,换个角度讲,包扫描没扫描到,会报错吗?不会,那问题区间缩小,很可能就是因为xml文件路径的问题。而其他配置文件是找到了的,不然它根本不会提示找不到(路径是写在mybatis-config.xml文件里的),既然我们确定了问题所在,这时候我们就需要尝试改变路径



w1.png

这时候我再去查博客,搜索的不是异常信息,而是配置文件的路径该怎么写?


在搜索的过程中我逐渐意识到我的项目结构可能与别人不同,所以我在搜索时加了Maven限定词,好家伙,不搜不知道,一搜我找到了原因所在。


原来Maven项目编译时会把文件全都输出到Target文件夹下面


q5.png


而默认情况下配置文件只会把resource文件夹下面的配置文件输出,这就造成Java文件夹下面的Mapper文件根本不会输出到target里,这样当然就找不到了,于是我修改了Maven项目中核心配置文件pom.xml信息,加入了下面的配置



q4.png

然后呢?


还是找不到…


本着不抛弃不放弃的精神,我开始关注target文件夹的文件结构



q3.png

什么,居然有两个com.dreamchser,这是为什么呢?


然后我开始测试加百度,然后发现了IDEA的神坑之处------当我们创建一个包时,com.dreamchser和com/dreamchaser是不同的!


com.dreamchaser就是指第二个圈里的包,com/dreamchaser指的是第一个圈里的包


.和/的差别真的是坑死我我了!


我仔细思考了下,之前查询博客的时候,确实有博客提到idea中创建包时/和.是不一样,但当时我以为我的mapper是被读取进去了,所以没在意,只是检查了其他部分,知道后面调试运行底层源码时MappedStatement这个对象的size=0,通过字面意思猜测mybatis实际上是没有读取进去的,进而开始了这方面的排查,最终找到了原因。



q2.png

如果用使用动态代理改造CRUD的方式,用接口实现,这意味着接口路径要和xml中那么namespace中的值一致,而在mybatis配置中mapper注册的时候路径要写的是被打包进target/classes下的路径,注意.和/ 的区别


q1.png


这次经历让我明白了该如何去解决问题。要解决问题的前提就是要知道问题的原因,需要定位问题,而不是报个错就盲目复制粘贴报错报错信息去搜博客,这确实可能会让你解决问题,但是有很大几率是你搜遍了网上的解决方式也没有解决问题,因为通常一个框架的同一个异常其实是有很多原因,你就会像无头苍蝇那样乱转,运气好可能会解决问题,运气不好就会到处碰壁。


九.必做题和附加题


1.必做题

此部分另外已提交,就不在此赘述了


2. 附加题

①题目要求

要求写出算法思想和代码


编写三个函数分别实现高精度加法、减法和乘法运算。在主函数中输入任意两个很大的正整数,可根据菜单提示,反复选择相应的操作进行计算。


菜单:1、输入任意两个正整数


2、高精度加法


3、高精度减法


4、高精度乘法


0、退出


②算法思想

我们知道正常的类型是无法存储这种大数值的,这里我们采用两个String来存储两个正整数,然后模拟我们平常计算加减乘除的过程来写代码,对每一位分别处理,最终得到我们想要的结果。


③代码

package com.dreamchaser;
import java.util.Scanner;
public class Main {
    static Scanner scanner = new Scanner(System.in);
    static String s1 = "";
    static String s2 = "";
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            if (choosePattern(1) == 1) {
                break;
            }
        }
    }
    private static int choosePattern(int i) {
        if (i == 1) {
            System.out.println("\n\n1.输入任意两个正整数");
            System.out.println("2.高精度加法");
            System.out.println("3.高精度减法");
            System.out.println("4、高精度乘法");
            System.out.println("0、退出");
            System.out.println("\n\n请输入你的选择(序号):");
        }
        switch (scanner.nextInt()) {
            case 1:
                //吃掉回车
                scanner.nextLine();
                print();
                return 0;
            case 2:
                add();
                return 0;
            case 3:
                delete();
                return 0;
            case 4:
                multiplication();
                return 0;
            case 5:
                return 1;
            default:
                System.out.println("抱歉,输入的是非法字符,请重新输入:");
                return choosePattern(0);
        }
    }
    private static void multiplication() {
        //表示进位
        int i, j, k;
        int[] c = new int[202];
        s1 = new StringBuilder(s1).reverse().toString();
        s2 = new StringBuilder(s2).reverse().toString();
        for (i = 0; i < s1.length(); i++) {
            for (j = 0; j < s2.length(); j++) {
                c[i + j] += (s1.charAt(i) - 48) * (s2.charAt(j) - 48);
            }
        }
        for (k = 1; k <= s1.length() + s2.length(); k++) {
            c[k] += c[k - 1] / 10;
            c[k - 1] %= 10;
        }
        while (c[k] == 0 && k >= 1) {
            k--;
        }
        for (; k >= 0; k--) {
            System.out.print(c[k]);
        }
        System.out.println();
    }
    private static void delete() {
        //表示进位
        int i, j, r = 0, k = 0;
        boolean flag = true;
        int[] c = new int[101];
        for (i = s1.length() - 1, j = s2.length() - 1; j >= 0; i--, j--) {
            //两个位数相减再减去接的位数
            c[k++] = (s1.charAt(i) - s2.charAt(j) - r);
            //清零标记
            r = 0;
            if (c[k - 1] < 0) {
                c[k - 1] += 10;
                r = 1;
            }//如果是负数就借十,并标记
        }
        //剩下的继续减
        while (i >= 0) {
            //减去借的
            c[k++] = (s1.charAt(i) - '0' - r);
            //清零标记
            r = 0;
            //如果是负数就借十,并标记
            if (c[k - 1] < 0) {
                c[k - 1] += 10;
                r = 1;
            }
            i--;
        }
        //输出
        for (i = k - 1; i >= 0; i--) {
            //防止前导0输出的操作
            if (c[i] != 0 || flag) {
                System.out.print(c[i]);
                flag = true;
            }
        }
        //如果都没有输出,说明相减结果为0,应当输出0
        if (flag == false) {
            System.out.print(0);
        }
        System.out.println();
    }
    private static void add() {
        //表示进位
        int i, j, r = 0, k = 0;
        boolean flag = true;
        int[] c = new int[101];
        //从最低位相加,相加他们的公共部分,所以j>=0
        for (i = s1.length() - 1, j = s2.length() - 1; j >= 0; i--, j--) {
            //两个位数和进位的相加后取个位
            c[k++] = (r + s1.charAt(i) - '0' + s2.charAt(j) - '0') % 10;
            //记录进位
            r = (r + s1.charAt(i) - '0' + s2.charAt(j) - '0') / 10;
        }
        //再把剩下的继续加
        while (i >= 0) {
            //位数和进位的相加后取个位
            c[k++] = (r + s1.charAt(i) - '0') % 10;
            //记录进位
            r = (r + s1.charAt(i) - '0') / 10;
            i--;
        }
        //如果还有进位,进到最高位
        if (r != 0) {
            c[k++] = r;
        }
        //输出
        for (i = k - 1; i >= 0; i--) {
            //防止前导0输出的操作
            if (c[i] != 0 || flag) {
                System.out.print(c[i]);
                ;
                flag = true;
            }
        }
        if (flag == false) {
            System.out.print(0);
        }
        System.out.println();
    }
    private static void print() {
        System.out.println("请输入第一个整数:");
        s1 = scanner.nextLine();
        System.out.println("请输入第二个整数:");
        s2 = scanner.nextLine();
        //把大的字符串放前面,方便操作
        if (s1.length() < s2.length() || (s1.length() == s2.length() && s1.compareTo(s2) > 0)) {
            String temp = "";
            temp = s1;
            s1 = s2;
            s2 = temp;
        }
    }
}


④测试结果

q4.png

q3.png


q2.png

q1.png



十、短学期实践的心得体会


花了三天时间写代码,一天时间写实验报告,总计四天的努力,累计超过千行的代码(确切是1632行,没错,我真的算了!),虽然过程艰辛,但是结果令人满意。


这个项目是我第一个独立完成的项目!说真的,很多东西你看似会了,但是真正到自己去做项目的时候,会发现很多问题,这个不会,那个不会,最后还是要靠百度解决,毕竟面向百度编程这句话不是可不是白讲的。


在这个过程中其实我也学到了很多,尤其是关于mybatis框架和Maven的认识更加深入了。而且这个过程中我渐渐形成了一套属于自己代码风格和编程习惯,而且我对于如何去定位查找解决bug也有了更加清晰的认识。


在这个过程中,我也认识到了自己的很多不足,未来我也要更加扎实的学习,更要尝试去多做项目,这样才能将知识技术化为内在,才能做到真正的融汇贯通,游刃有余!



相关文章
|
2月前
|
前端开发 Java 关系型数据库
SpringBoot+MyBatis 天猫商城项目
SpringBoot+MyBatis 天猫商城项目
80 1
|
2月前
|
NoSQL Java 数据库连接
SpringBoot-搭建Mybatis项目
通过本文的学习,读者将了解如何使用IntelliJ IDEA快速搭建一个基于SpringBoot和Mybatis的Java Web应用程序,提高开发效率。
71 0
|
2月前
|
前端开发 Java 数据库连接
Springboot-MyBatis配置-配置端口号与服务路径(idea社区版2023.1.4+apache-maven-3.9.3-bin)
Springboot-MyBatis配置-配置端口号与服务路径(idea社区版2023.1.4+apache-maven-3.9.3-bin)
39 0
|
2天前
|
Java 数据库连接 数据库
大事件后端项目05-----springboot整合mybatis
大事件后端项目05-----springboot整合mybatis
大事件后端项目05-----springboot整合mybatis
|
6天前
|
Java 程序员
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
19 1
|
12天前
|
Java 数据库连接 Apache
JavaWeb基础第二章(Maven项目与MyBatis 的快速入门与配置)
JavaWeb基础第二章(Maven项目与MyBatis 的快速入门与配置)
|
17天前
|
安全 Java 数据库连接
Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台项目
Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台项目
29 0
|
2月前
|
Web App开发 前端开发 JavaScript
Spring Boot整合 mybatisplus(后端) Vue+echarts+Element UI+axios(前端)---前后端项目实例demo
Spring Boot整合 mybatisplus(后端) Vue+echarts+Element UI+axios(前端)---前后端项目实例demo
62 1
|
2月前
|
XML Java 数据库连接
Mybatis-Plus学习小项目及详细教程
Mybatis-Plus学习小项目及详细教程
|
2月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制

相关实验场景

更多