Mybatis应用(3)——mybatis框架使用 & mybatis项目应用初步 & mybatis使用报错集锦_[error] 读取c users xyp (1)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

<plugins>
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <property name="dialect" value="mysql"/>
    </plugin>
</plugins>

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
            <property name="username" value="root"/>
            <property name="password" value="123"/>
        </dataSource>
    </environment>
</environments>
<mappers>
    <package name="com.tianju.dao"/>
</mappers>

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" ?>

![在这里插入图片描述](https://img-blog.csdnimg.cn/3120bb5a463149b89f9addaacfea6fe9.png)


### 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> T getMapper(Class<T> mapperClass){return sqlSession.getMapper(mapperClass);};


getMapper方法—泛型T


![在这里插入图片描述](https://img-blog.csdnimg.cn/dd3e93039f5e4a3ba80943dae2208f35.png)


![在这里插入图片描述](https://img-blog.csdnimg.cn/a3f2abeb36164d608c7bd8d64f65f6a7.png)



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> T getMapper(Class<T> mapperClass){
    return sqlSession.getMapper(mapperClass);
}

}


### 2.多条件查询<where, if>,传入Boolean


![在这里插入图片描述](https://img-blog.csdnimg.cn/1c22d18eec6c4726a9ce0904b03b1963.png)



@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// 排序
);



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 ownerName
    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

    <where>
        <if test="buildingId!=null">
            c_building.id=#{buildingId}
        </if>
        <if test="storey!=null">
            AND c_house.storey=#{storey}
        </if>
        <if test="areaMin!=null">
            AND c_house.area &gt;= #{areaMin}
        </if>
        <if test="areaMax!=null">
            AND c_house.area &lt;= #{areaMax}
        </if>
        <if test="intoDateBegin!=null">
            AND c_house.into_date &gt; #{intoDateBegin}
        </if>
        <if test="intoDateEnd!=null">
            AND c_house.into_date &lt;= #{intoDateEnd}
        </if>
        <if test="roomNum!=null and roomNum!=''">
            AND roomNum LIKE #{roomNum}
        </if>
    </where>
    <if test="areaOrderASC">
        ORDER BY c_house.area
    </if>
    <if test="areaOrderDESC">
        ORDER BY c_house.area DESC
    </if>
</select>

service层使用



@Autowired
private HouseMapper houseMapper;
@Override
public PageInfo<House> 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<House> 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);



<select id="queryHouseByBuildingId" resultType="house">
    SELECT * FROM c_house

    WHERE
    building_id IN
    <foreach collection="buildingIdList" open="(" separator="," close=")" item="id">
        #{id}
    </foreach>
    <choose>
        <when test="status!=null and status.length>0 and !status[0]">
        </when>
        <otherwise>
            AND !status
        </otherwise>
    </choose>
</select>

### 4.多条件查询进阶版<where,choose,when,otherwise,foreach,if>


![在这里插入图片描述](https://img-blog.csdnimg.cn/b415b01821ec4e218eb995ca6fc4cac1.png)



/\*\*

* 查询所有空闲的房子,显示到左边的框里面 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 id="queryAllNoIntoHouse" resultType="house">
    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 ownerName

    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

    <where>
        <choose>
            <when test="buildingIdList!=null and buildingIdList.size()>0">
                building_id IN
                <foreach collection="buildingIdList" open="(" separator="," close=")" item="id">
                    #{id}
                </foreach>
            </when>
            <otherwise>
            </otherwise>
        </choose>

        <if test="storey!=null">
            AND c_house.storey=#{storey}
        </if>
        <if test="areaMin!=null">
            AND c_house.area &gt;= #{areaMin}
        </if>
        <if test="areaMax!=null">
            AND c_house.area &lt;= #{areaMax}
        </if>
        <choose>
            <when test="status!=null and status.length>0 and !status[0]">
                <!-- 如果为false,则可以查询到非空闲房子-->
            </when>
            <otherwise>
                AND !status
            </otherwise>
        </choose>
    </where>
    <if test="areaOrderASC">
        ORDER BY c_house.area
    </if>
    <if test="areaOrderDESC">
        ORDER BY c_house.area DESC
    </if>
</select>

前后端交互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<House> list = houseService.queryAllNoIntoHouse(buildingIds, storey, areaMin, areaMax, areaOrderASC, areaOrderDESC, true);
    list.forEach(System.out::println);
    return new ResData(200, "ok", list);
}

前端代码



新增业主

录入业主基础信息:
用户名:   真实姓名: 电话号码:
身份证号:<input type="text" v-model="identity">
性别:
<input type="radio" v-model="gender" value="男">男
<input type="radio" v-model="gender" value="女">女
<br>
备注信息:<textarea v-model="notes" rows="3" cols="22"></textarea><br>
<br>
录入选房信息:<br>
<div>
    楼栋编号:
    <select v-model="buildingId">
        <option value="">--请选择楼栋--</option>
        <option v-for="building in buildingList" :value="building.id">{{building.num}}-{{building.unit}}</option>
    </select>
    <button @click="addBuildingId">添加楼栋</button>
    <button @click="resetSelectBuildsBtn">重选楼栋</button>
    <br>

    选中的楼栋为:
    <select multiple style="width: 100px" @dbclick="removeSelectedBuildingsBtn">
        <option v-for="building in selectedBuildingList" :value="building.id">{{building.num}}-{{building.unit}}</option>
    </select>
    楼层:
    <select v-model="selectFloor">
        <option value="">-选择楼层--</option>
        <option v-for="floors in floorList" :value="floors">{{floors}}层</option>
    </select>
    面积:
    <input type="text" v-model="areaMin" style="width: 50px" placeholder="小">---
    <input type="text" v-model="areaMax" style="width: 50px" placeholder="大">

    <button @click="areaASC">面积升序</button>
    <button @click="areaDESC">面积降序</button>

    <button @click="searchHouseBtn">搜索房子</button>
    <button @click="searchHouseBtnClr">重置搜索</button><br>
</div>
可选的房子为:
<select multiple style="width: 200px" @dblclick="selectHouseDbc">
    <option v-for="house in canSelectHouse" :value="house.id">
        {{house.num}}--{{house.unit}}--{{house.roomNum}}--{{house.area}}
    </option>
</select>

选中的房子为:
<select  multiple style="width: 200px" @dblclick="removeSelectedHouseDbc">
    <option v-for="house in selectedHouse" :value="house.id">
        {{house.num}}--{{house.unit}}--{{house.roomNum}}--{{house.area}}平米
    </option>
</select>
<br>
<button @click="add">添加</button>
<button @click="reset">重置</button><br>
<br>

专门用来前后端交互的实体类



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
);



<select id="queryManagerById" resultType="user">
    SELECT * FROM
    (SELECT
    user_manager.id,
    user_role.id AS userRoleId,user_role.role_id AS typeId,user_role.user_id AS userId,
    user_manager.username,user_manager.password,user_manager.tel,
    user_manager.notes AS userNotes,user_manager.create_time,user_manager.update_time,
    user_manager.operator,user_manager.status,user_manager.firstLog,
    user_role_type.name AS typeName,user_role_type.notes AS typeNotes
    FROM user_manager
    LEFT JOIN user_role ON user_manager.id = user_role.user_id
    LEFT JOIN user_role_type ON user_role.role_id = user_role_type.id
    ) t
    WHERE t.id = #{id}
    <!-- 一般人员只能查询在职员工,超级管理员可以查所有员工-->
    <choose>
        <when test="su==null or su.length &lt; 1">
            AND firstLog !='100' AND status
        </when>
    </choose>

</select>

![在这里插入图片描述](https://img-blog.csdnimg.cn/43d41019692a44a58798838799222e56.png)


### 6.多个条件排序 ORDER BY num,unit


![在这里插入图片描述](https://img-blog.csdnimg.cn/459e5c20d712447cb869a092b496680d.png)


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<Building> pageInfo = buildingService.queryAll(pageSize, pageNum,order);
    System.out.println(pageInfo);
    return new ResData(200,"ok",pageInfo);

}

service层



@Override
public PageInfo<Building> queryAll(Integer pageSize,Integer pageNum,Boolean order) {
    PageHelper.startPage(pageNum, pageSize);
    List<Building> list = buildingMapper.queryAll(order);
    return new PageInfo<>(list);
}

mapper层



List queryAll(Boolean order);


xml文件的sql



<select id="queryAll" resultType="building">
    SELECT * FROM c_building
    <if test="order">
        ORDER BY num,unit
    </if>
</select>

### 7.一条新增影响多个数据库的表@Transactional


![在这里插入图片描述](https://img-blog.csdnimg.cn/e5da64d27aab4bd784ad1dcb130d9016.png)


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;
}


<update id="intoHouse">
    UPDATE c_house SET into_date = NOW(),status=1 WHERE id=#{id}
</update>

<insert id="addOwnerHouse">
    INSERT INTO c_owner_house(ownerId,houseId) VALUES (#{ownerId},#{houseId})
</insert>

## 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.


报错原因:


查询返回值类型没写


![在这里插入图片描述](https://img-blog.csdnimg.cn/a0884b3ffed94fc4beaed7ca2c800f2d.png)


解决方案:


加上resultType=“opus”,如下:



<select id="queryByAuthorIdAndLikeName" 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
    <where>
        <if test="authorId!=null">
            authorId = #{authorId}
        </if>
        <if test="name!=null and name!=''">
            AND t_opus.name LIKE #{name}
        </if>
    </where>
    ORDER BY t_opus.id DESC
</select>

### 2.前端显示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}


原因分析:


pageHelper有顺序要求


![在这里插入图片描述](https://img-blog.csdnimg.cn/4c0d686ac7c54dfcbbf74f8b098bfd59.png)


解决方案:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2c121291a4f342b8927b01eb9d406c13.png)



/\*\*

* 分页在service层完成,利用pageHelper 在service层做完分页的事情
*/
@Override
public PageInfo queryByAuthorIdAndLikeName(String name, Integer authorId, Integer pageNum,Integer pageSize) {
// 先要用pageHelper的 分页,然后执行查询
PageHelper.startPage(pageNum, pageSize);
List list = opusMapper.queryByAuthorIdAndLikeName(name, authorId);
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
}


### 3.由于mybatis版本引起的问题


报错信息:


org.apache.ibatis.exceptions.PersistenceException:


Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘username’ in ‘class java.lang.String’


Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘username’ in ‘class java.lang.String’


报错原因


如果3.4.5版本,3.4开头的就是低版本,并且username要在动态sql中使用,即,if,where,中使用,则一个参数也需要加@param,如果是3.5.9以上版本,则可以不加


![在这里插入图片描述](https://img-blog.csdnimg.cn/6d3d330b80374b338dc797d211de70b7.png)


解决方案:


1.UserMapper里面加@param



// 如果3.4.5版本,3.4开头的就是低版本,并且username要在动态sql中使用
// 即,if,where,中使用,则一个参数也需要加@param,如果是3.5.9以上版本,则可以不加
List findByUsernameSQL(@Param(“username”) String username);


2.mybatis版本换成3.5以上



    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>

在项目中的案例:


![在这里插入图片描述](https://img-blog.csdnimg.cn/a97c3cd2ee77490f9394523a199e153b.png)


接口java文件



img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

即,if,where,中使用,则一个参数也需要加@param,如果是3.5.9以上版本,则可以不加

在这里插入图片描述

解决方案:

1.UserMapper里面加@param

// 如果3.4.5版本,3.4开头的就是低版本,并且username要在动态sql中使用
    // 即,if,where,中使用,则一个参数也需要加@param,如果是3.5.9以上版本,则可以不加
    List<User> findByUsernameSQL(@Param("username") String username);

2.mybatis版本换成3.5以上

<!-- mybatis 框架-->
<!-- 小版本会导致userMapper findByUsernameSQL-->
<!-- 3.5.9-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

在项目中的案例:

在这里插入图片描述

接口java文件



[外链图片转存中...(img-B3tAmbTl-1715063093188)]
[外链图片转存中...(img-8c87Q1pA-1715063093188)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618608311)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值