先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
正文
application.yml配置文件
server:
port: 82
1.连接数据库——对应之前 xml文件的数据库
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/community?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: 123
TODO:设置上传文件大小
servlet:
multipart:
max-file-size: 10MB # 设置单个文件最大大小为10MB
mybatis其他配置
mybatis:
2.给实体类起别名,首字母小写
type-aliases-package: com.tianju.entity
configuration:
3.开启驼峰命名
map-underscore-to-camel-case: true
4.让日志生效
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5.扫描sql的位置
mapper-locations: classpath:/mapper/*Mapper.xml
全局的一个路径,用@Values获取
repairImg: D:/620/repair/
日志的相关配置
logging:
file:
name: D:\620\log\community.log
level:
org.springframework.web: debug
com.tianju: debug
org.springframework.jdbc.support.JdbcTransactionManager: debug
2.resources下配置mybatis-config.xml文件,以及log4j.properties文件
my-batis-cofig.xml
要点:
(1)开启驼峰命名;(2)日志生效;(3)给所有实体类起别名;(4)分页工具PageHelper要加拦截器;(5)配置连接数据库相关的driver,url,username,password;其中url需要在&后面加 amp;
(6)配置mapper,采用简化的方式,用<package,点的方式
<?xml version="1.0" encoding="UTF-8" ?>log4j.properties文件:
Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
#log4j.rootCategory=debug, CONSOLE, LOGFILE
log4j.rootCategory=debug, CONSOLE
Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
3.在resources下建文件
<?xml version="1.0" encoding="UTF-8" ?>4.在UserMapper中写SQL
要点:
(1)update,delete,insert不要写成select,不然会出现删除数据后,数据库确实删除了,但是前端list还有;
(2)if语句中不要忘记加逗号:
(3)select语句中,要记得加返回值;
mybatis项目应用
1.封装SqlSessionUtils.java工具类
要点:
- 读取mybatis配置文件,告诉那里读取;
- 生成一个建造sqlSession工厂的建造者,SqlSessionFactoryBuilder;
- 建造者SqlSessionFactoryBuilder根据mybatis-config.xml建造一个SqlSession工厂,SqlSessionFactory;
- 在SqlSession工厂中,通过SqlSessionFactory生成一个sqlSession,且打开自动提交sqlSession = sqlSessionFactory.openSession(true);
- 需要什么类型的mapper就提供什么类型的mapper,public static T getMapper(Class mapperClass){return sqlSession.getMapper(mapperClass);};
getMapper方法—泛型T
package com.tianju.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SqlSessionUtils {
private static SqlSession sqlSession;
static {
//1.读取mybatis配置文件
InputStream is = null;
try {
is = Resources.getResourceAsStream(“mybatis-config.xml”);
} catch (IOException e) {
throw new RuntimeException(e);
}
//2.生成一个工厂–这个工程是通过建造者建造出来的
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.建造者根据mybatis-config.xml建造一个SqlSession工厂
SqlSessionFactory sqlSessionFactory = builder.build(is);
//4.通过sqlSessionFactory生成一个sqlSession
sqlSession = sqlSessionFactory.openSession(true);
//如果设置为true,每次自动提交
}
public static T getMapper(Class mapperClass){
return sqlSession.getMapper(mapperClass);
}
}
2.多条件查询<where, if>,传入Boolean
@Mapper
public interface HouseMapper {
List queryList(
@Param(“buildingId”) Integer buildingId, // 楼栋
@Param(“storey”) Integer storey, // 楼层
@Param(“roomNum”) String roomNum, // 房间号
@Param(“areaMin”) Double areaMin, // 面积
@Param(“areaMax”) Double areaMax, // 面积
@Param(“intoDateBegin”) Date intoDateBegin, // 入住开始时间
@Param(“intoDateEnd”) Date intoDateEnd, // 入住结束时间
@Param(“areaOrderASC”) Boolean areaOrderASC,
@Param(“areaOrderDESC”) Boolean areaOrderDESC// 排序
);
FROM c_house
LEFT JOIN c_building ON c_building.id = c_house.building_id
LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId
service层使用
@Autowired
private HouseMapper houseMapper;
@Override
public PageInfo queryList(Integer buildingId, Integer storey, String roomNum, Double areaMin, Double areaMax, Date intoDateBegin, Date intoDateEnd,
Integer pageNum, Integer pageSize,
Boolean areaOrderASC, Boolean areaOrderDESC) {
PageHelper.startPage(pageNum,pageSize);
List list = houseMapper.queryList(buildingId,storey,roomNum,areaMin,areaMax,intoDateBegin,intoDateEnd,areaOrderASC,areaOrderDESC);
return new PageInfo<>(list);
}
3.多条件查询IN,foreach+可变长度参数<choose,when,otherwise>,传入list
/**
* 查询空闲的房子,根据buildingId查询,忽略单元
* @param buildingIdList 根据buildingId查询房间,默认查询空间房间,如果status为false,
* 则也可以查询到非空闲的房间
* @param status 默认为true,如果为false,则可以查询到非空闲房子
* @return
*/
List queryHouseByBuildingId(
@Param(“buildingIdList”) List buildingIdList,
@Param(“status”) Boolean… status);
WHERE
building_id IN
#{id}
4.多条件查询进阶版<where,choose,when,otherwise,foreach,if>
/**
* 查询所有空闲的房子,显示到左边的框里面 TODO:后面再全查询的基础上进行
*/
List queryAllNoIntoHouse(
@Param(“buildingIdList”) List buildingIdList, // 楼栋
@Param(“storey”) Integer storey, // 楼层
@Param(“areaMin”) Double areaMin, // 面积
@Param(“areaMax”) Double areaMax, // 面积
@Param(“areaOrderASC”) Boolean areaOrderASC,
@Param(“areaOrderDESC”) Boolean areaOrderDESC,// 排序
@Param(“status”) Boolean… status // 如果为false,则可以查询到非空闲房子,其他情况 都是查询空闲房子
);
SELECT c_house.id, c_owner_house.ownerId, c_building.num,c_building.floors,c_building.unit, c_house.storey,c_house.roomNum,c_house.area,c_house.into_date,c_house.status,c_house.building_id, user_owner.realname AS ownerNameFROM c_house
LEFT JOIN c_building ON c_building.id = c_house.building_id
LEFT JOIN c_owner_house ON c_owner_house.houseId = c_house.id
LEFT JOIN user_owner ON user_owner.id = c_owner_house.ownerId
前后端交互controller层
// 2.处理搜索请求
// 默认显示所有可以选择的房间,放到左侧的框里,如果选择,双击,这条数据跳到右边的框里
@RequestMapping(“/query/house”)
@ResponseBody
public ResData queryHouse(
// @RequestParam(value = “buildingList”, defaultValue = “List[]”) List buildingList, // 楼栋
// Integer storey, // 楼层,没有用到
// Double areaMin,
// Double areaMax,
// @RequestParam(value = “areaOrderASC”,defaultValue = “false”) Boolean areaOrderASC,
// @RequestParam(value = “areaOrderDESC”,defaultValue = “false”) Boolean areaOrderDESC
@RequestBody HouseFront houseFront
){
Double areaMax = houseFront.getAreaMax();
Double areaMin = houseFront.getAreaMin();
Boolean areaOrderASC = houseFront.getAreaOrderASC();
Boolean areaOrderDESC = houseFront.getAreaOrderDESC();
Integer storey = houseFront.getStorey();
List buildingList = houseFront.getBuildingList();
List buildingIds = buildingList.stream().map(Building::getId).collect(Collectors.toList());
System.out.println(“查询条件:”
+areaMin+“/”
+areaMax+“/”
+buildingIds+“/”
+storey+“/”
);
// 大小的问题
if (!StringUtils.isBlank(areaMin) && !StringUtils.isBlank(areaMax)){
if (areaMin.compareTo(areaMax)>0){
return new ResData(1002, “最小面积不能大于最大面积”, null);
}
}
// 这个排序顺序不能两个都是true
if (areaOrderASC && areaOrderDESC){
return new ResData(1003, “排序条件冲突”, null);
}
List list = houseService.queryAllNoIntoHouse(buildingIds, storey, areaMin, areaMax, areaOrderASC, areaOrderDESC, true);
list.forEach(System.out::println);
return new ResData(200, “ok”, list);
}
前端代码
录入业主基础信息:
用户名: 真实姓名: 电话号码:
身份证号:
性别:
男
女
备注信息:
录入选房信息:
选中的楼栋为:
<select multiple style=“width: 100px” @dbclick=“removeSelectedBuildingsBtn”>
<button @click=“areaASC”>面积升序
<button @click=“areaDESC”>面积降序
<button @click=“searchHouseBtn”>搜索房子
<button @click=“searchHouseBtnClr”>重置搜索
可选的房子为:
<select multiple style=“width: 200px” @dblclick=“selectHouseDbc”>
选中的房子为:
<select multiple style=“width: 200px” @dblclick=“removeSelectedHouseDbc”>
专门用来前后端交互的实体类
package com.tianju.entity;
import com.alibaba.druid.filter.AutoLoad;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 专门用来和前端交互的一个对象;
* 用于选房页面的复杂查询
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HouseFront {
private List buildingList;
private Integer storey;
private Double areaMin;
private Double areaMax;
private Boolean areaOrderASC;
private Boolean areaOrderDESC;
}
5.传入Boolean类型的可变长度参数
/**
* 超级管理员能看离职员工和在职员工的信息,
* 其他员工只能看在职员工信息。
* @param su 表示是否是超级管理员,su 为true 时,为超级管理员
* @return
*/
List queryAllManagerUser(
@Param(“su”) Boolean… su
);
6.多个条件排序 ORDER BY num,unit
controller层
@RequestMapping(“/list”)
@ResponseBody
public ResData buildingList(
@RequestParam(value = “pageNum”,defaultValue = “1”)Integer pageNum,
@RequestParam(value = “pageSize”,defaultValue = “10”)Integer pageSize,
@RequestParam(value = “order”,defaultValue = “false”)Boolean order){
PageInfo pageInfo = buildingService.queryAll(pageSize, pageNum,order);
System.out.println(pageInfo);
return new ResData(200,“ok”,pageInfo);
}
service层
@Override
public PageInfo queryAll(Integer pageSize,Integer pageNum,Boolean order) {
PageHelper.startPage(pageNum, pageSize);
List list = buildingMapper.queryAll(order);
return new PageInfo<>(list);
}
mapper层
List queryAll(Boolean order);
xml文件的sql
SELECT * FROM c_building ORDER BY num,unit7.一条新增影响多个数据库的表@Transactional
controller层
// 3.处理新增用户信息
Boolean addFlag = true;
@RequestMapping(“/add”)
@ResponseBody
public ResData addOwner(
@RequestBody Owner owner
){
System.out.println(owner);
// 1.判断前端输入的数据全不
// 2.如果确认不新添房子,则只修改user_owner表,则该用户不能登陆账号
// 3.如果新增了房子,则修改user_owner表,c_house表,c_owner_house表
if (StringUtils.isBlank(owner.getUsername(),owner.getRealname(),owner.getIdentity(),owner.getGender())){
return new ResData(1001, “必填项为空”, null);
}
if (!StringUtils.isLegalPhone(owner.getTel())){
return new ResData(1002, “手机号码不合法”, null);
}
// TODO:这样可以吗???
if (addFlag){
if (owner.getHouseList().size()<1){
addFlag = false;
return new ResData(2001, “确定新增一条未选择房间的业主?”, null);
}
}
// 初始化一下密码,手机号前4位
owner.setPassword(owner.getTel().substring(0,4));
// 获取session
User user = (User) session.getAttribute(“user”);
if (user!=null){
owner.setOperator(user.getOperator());
}
Integer flag = ownerService.add(owner);
if (flag<1){
return new ResData(3001, “系统繁忙,请稍后重试”, null);
}
addFlag = true; // 新增成功再置为true,下一条就会再次判断是不是没填
return new ResData(200,“新增用户信息成功”,null);
}
service层@Transactional
@Transactional
@Override
public Integer add(Owner owner) {
// 如果新用户只是意向客户
if (owner.getHouseList().size()<1){
owner.setHouseNum(0);
return ownerMapper.add(owner);
}
// 买房的客户变成了业主
Integer num = 0; //影响数据库的数据的行数
ownerMapper.add(owner);
for (House house:owner.getHouseList()){
// 房间状态改为入住的状态
houseMapper.intoHouse(house.getId());
// 房屋-业主对应表新增一条数据
houseMapper.addOwnerHouse(owner.getId(), house.getId());
num +=2;
}
return num;
}
mybatis使用报错集锦
1.忘记加 resultType=“opus”
报错信息:
Error querying database. Cause: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement ‘com.tianju.dao.OpusMapper.queryByAuthorIdAndLikeName’. It’s likely that neither a Result Type nor a Result Map was specified.
报错原因:
查询返回值类型没写
解决方案:
加上resultType=“opus”,如下:
SELECT t_opus.*,tt.name AS typename,tu.username FROM t_opus LEFT JOIN t_types tt ON t_opus.typeId = tt.id LEFT JOIN user_tab tu ON t_opus.authorId = tu.id authorId = #{authorId} AND t_opus.name LIKE #{name} ORDER BY t_opus.id DESC2.前端显示list页面数据为空
问题描述:
pageHelper里面的没有数据,前端显示为空:
PageInfo{pageNum=0, pageSize=0, size=0, startRow=0, endRow=0, total=0, pages=0, list=null, firstPage=0, prePage=0, nextPage=0, lastPage=0, isFirstPage=false, isLastPage=false, hasPreviousPage=false, hasNextPage=false, navigatePages=0, navigatepageNums=null}
原因分析:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
n/a0884b3ffed94fc4beaed7ca2c800f2d.png)
解决方案:
加上resultType=“opus”,如下:
SELECT t_opus.*,tt.name AS typename,tu.username FROM t_opus LEFT JOIN t_types tt ON t_opus.typeId = tt.id LEFT JOIN user_tab tu ON t_opus.authorId = tu.id authorId = #{authorId} AND t_opus.name LIKE #{name} ORDER BY t_opus.id DESC2.前端显示list页面数据为空
问题描述:
pageHelper里面的没有数据,前端显示为空:
PageInfo{pageNum=0, pageSize=0, size=0, startRow=0, endRow=0, total=0, pages=0, list=null, firstPage=0, prePage=0, nextPage=0, lastPage=0, isFirstPage=false, isLastPage=false, hasPreviousPage=false, hasNextPage=false, navigatePages=0, navigatepageNums=null}
原因分析:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-xZfGoKab-1713336282032)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!