当前位置: 首页 > 后端技术 > Java

本周遇到的问题

时间:2023-04-01 21:04:36 Java

删除类时出错添加新类后删除类时出错,但是单元测试的时候没有报错,正常通过。错误消息是Servlet.service()forservlet[dispatcherServlet]incontextwithpath[]throwedexception[Requestprocessingfailed;嵌套异常是org.springframework.dao.InvalidDataAccessApiUsageException:Thegivenidmustnotbenull!;嵌套异常是java.lang.IllegalArgumentException:Thegivenidmustnotbenull!]withrootcause关键句是Thegivenidmustnotbenull!.然后去web控制台查看错误信息是500,确认是后台发生的错误。然后到C层用logger.info()打印发现前台传过来的id为null,然后查看单元测试中的内容@Testpublicvoiddelete(){Teacherteacher=newTeacher();类类=新类类();klass.setName("测试123123类");klassRepository.save(类);klassService.delete(klass.getId());可选klassOptional=klassRepository.findById(klass.getId());Assertions.assertThat(klassOptional.isPresent()).isFalse();}发现单元测试中的classID是直接调用klass.getId()得到的id,然后返回C层查看,发现在delete方法中的参数没有使用@PathVariable注解.单元测试不检测前台数据是否传递给后台。这意味着写好后台后,首先要测试前台的数据能否传到后台。删除班级绑定的教师时出错。当老师绑定班级时,不应删除。但是在删除的时候,前台应该给出相应的提示或者把绑定的班级一起删除(或者unbind,即将teacher_id设置为空),而不是报500错误。报错信息是:Cannotdeleteorupdateaparentrow:aforeignkeyconstraintfails这里,先尝试第二种方案。出现这个错误的原因是:你要删除的数据或表与其他数据或表有主键和外键关系,Mysql规定为了保持表结构的稳定性,禁止该操作,即外键约束失败。如果我们想强制删除,可以执行如下语句:Stringsql=String.format("deletefrom`teacher`whereid=%s",id);this.jdbcTemplate.update("SETforeign_key_checks=0");this.jdbcTemplate.update(sql);this.jdbcTemplate.update("SETforeign_key_checks=1");操作后可以删除老师,但是对应的班级还没有删除,查看班级也会报错。我们可以执行如下语句来操作类Teacherteacher=newTeacher();teacher=this.teacherService.getById(id);RowCallbackHandlerrowCallbackHandler=newRowCallbackHandler(){@OverridepublicvoidprocessRow(ResultSetresultSet)throwsSQLException{Klass类=新类();klass.setTeacher(null);klass.setName(resultSet.getString("name"));klass.setId(resultSet.getLong("id"));klassService.update(klass.after还发现找到老师对应的类可以直接通过CrudRepository中的方法实现,我们只需要在Repository中声明我们要使用的方法即可。我们不需要写sql代码,所以上面的代码也可以简化为publicvoiddelete(Longid){Teacherteacher;teacher=this.teacherService.getById(id);列表klasses=klassService.findAllByTeacher(teacher);klasses.forEach(klass->{klass.setTeacher(null);klassService.update(klass.getId(),klass);});teacherRepository.deleteById(id);}这时候如果我们再删除teacher,会把删除班级的teacher设置为空,实现teacher的正常删除。另外,当我们要删除一个老师的时候,如果这个老师有班级,我们会直接给出提示——这个老师绑定了一个班级,不能删除来解决问题。在前台我们可以先查看后台是否有绑定老师的班级要删除,如果有则提示——删除失败,且有绑定老师的班级。前台代码onDelete(teacher:Teacher):void{constindex=this.teachers.indexOf(teacher);this.httpClient.get(`${this.url}haveKlass/${teacher.id}`).subscribe((flag)=>{console.log(flag);if(flag){console.log('删除失败,有一个类绑定到这个老师');}else{this.httpClient.delete(`${this.url}/${teacher.id}`).subscribe(()=>{this.teachers.splice(index,1);console.log('删除成功');},error=>console.log('删除错误',error));}});}后台haveKlass接口对应代码:publicBooleanhaveKlass(Longid){finalBoolean[]flag=newBoolean[1];标志[0]=假;RowCallbackHandlerrowCallbackHandler=newRowCallbackHandler(){@OverridepublicvoidprocessRow(ResultSetresultSet)throwsSQLException{flag[0]=true;}};字符串newSql=字符串。格式(“选择tid,name,teacher_idfromklasswhereteacher_id=%d",id);jdbcTemplate.query(newSql,rowCallbackHandler);returnfonglilag[0];}同理,上述代码可以简化为publicBooleanhaveKlass(Longid){returnklassService.existsByTeacher(teacherService.getById(id));}JAVA中String/Boolean...和string/boolean的区别以boolean为例,boolean是java中最基本的8种类型之一,而java为8基本类型提供了一个封装类来表示一个对象,但是在一些框架中,比如要求参数和值是对象类型,所以不能使用基本类型,boolean是基本数据类型。Boolean是它的封装类,和其他类一样,有属性和方法,可以new,例如:Booleanflag=newBoolean("true");//不允许boolean!添加@Column(unique=true)注解不起作用,一开始以为是后台没有重启,但是重启后仍然可以存储同一个学号的学生(不管是前台还是单元测试),索引项打开数据库时,Student表不会更新。sno字段对应的类型是UNIQUE。查询后发现,这些设置只有在新建表Update时才有,即使连接方式为update,也不会相应更新。但是,当使用@Column(nullable=false)将值设置为非空时,无需重建表即可实现。可见是否需要重建表与这个注解没有直接关系。它与要设置的选项有关。单元测试中的数据和背景是双向绑定的。在测试数据的唯一性时,出现如下测试代码。私人课程;私人学生学生;@TestpublicvoidsnoUniqueTest(){booleancalled=false;this.studentRepository.save(this.student);System.out.println(this.student.getId());//2--尝试输出IDtry{this.before();//为什么还要调用before()this.studentRepository.save(this.student);}catch(DataIntegrityViolationExceptione){called=true;}System.out.println(this.student.getId());//3--尝试输出ID(4)Assertions.assertThat(called).isTrue();}@Beforepublicvoidbefore(){this.student=newStudent();如果(this.klass==null){this.klass=newKlass();this.klassRepository.save(this.klass);}this.student.setSno("123456");this.student.setName("考试名称");this.student.setKlass(this.klass);System.out.println(this.student.getId());//1--尝试输出ID(3)}去掉后执行测试this.before没有调用时为false,再尝试输出学生的ID,对应以上三个位置。调用this.before()时,输出结果对应-null,1,null,null;注释掉this.before()后,输出结果为-null,1,1;也就是说之前创建的student是不带id的。当我们保存到数据库中时,数据库会自动给它附加一个ID,然后测试中的实体也会给数据库附加一个ID。这时候再次调用save()方法时,因为ID相同,自然会默认更新一条数据,不会出错。当我们再次调用before()时,创建了一个新对象,ID为空。这个时候我们调用save方法表示我们要存储数据,但是因为字段的设置不允许存储相同的字段,所以会报错。它符合我们的期望。