今天学习Mybatis遇到几个问题, 记录一下我当时的情况和解决过程
- Invalid bound statement 错误
- There is no getter for property named ‘id’ in ‘class java.lang.Long’ 错误
我的代码是这样的, 然后我说一下当时碰到的问题
- 接口代码
package com.crb.mapper;
public interface UserMapper {
/**
* 按id查询用户
* @param id 用户id
* @return 用户
*/
SysUser selectById(Long id);
}
- Mybatis全局配置文件
<mappers>
<package name="com.crb.mapper"/>
</mappers>
- xml映射文件
<!--接口和XML是通过这个namespace的全限定类名进行绑定的-->
<mapper namespace="com.crb.mapper.UserMapper">
<resultMap id="userMap" type="com.crb.model.SysUser">
<id property="id" column="Id"/>
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<result property="userEmail" column="user_email"/>
<result property="userInfo" column="user_info"/>
<result property="headImg" column="head_img" jdbcType="BLOB"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
<!--select标签的id和接口中的方法进行关联-->
<!--resultMap用于设置返回值的类型和映射关系。resultMap标签中的值对应上边resultMap的id. 通过ID引用需要的resultMap-->
<select id="selectById" resultMap="userMap">
select * from mybatis.sys_user where id = #{id}
</select>
</mapper>
1. Invalid bound statement
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.crb.mapper.UserMapper.selectById
" com.crb.mapper.UserMapper.selectById " 是当时我写的包名.接口名.方法名
搜索引擎搜索了好多博客, 基本说的都差不多. 名称写错, 没有对应等等
当时的思路
- 确认过每一个路径和名称, 没有问题
- 更改了全局配置文件, 使用相对于类路径的资源引用, 正常显示了我想要看到的结果, 那也就是说, 是没有找到xml映射文件, 并不是找不到那个方法
- 换回接口路径的映射器扫描, 开始想是哪的问题, 无意中看到了target目录的目录结构
- xml映射文件和接口文件没有在一个目录下
- 更改resources目录下mapper目录为接口所在包名 (这里有一个IDEA的’坑’, 我在最后讲一下)
- 执行了clean和compile
- 测试类通过了
解决方案
所以最后我遇到的这个问题是 xml映射文件和对应的接口不在一个目录下, 所以报错
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
<!-- 顺便列举一下四种配置方式 -->
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<!-- 上边提到'使用相对于类路径的资源引用'是这个 -->
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
对于我碰到的这个问题, 是因为我把Idea当成了Eclipse
先看一下项目的目录结构 (多了一个UserMapper.xml是因为我总删除目录, 留作备份的)
再看一下有问题目录结构
细心的你肯定发现了目录结构有问题, 当时我就奇怪为什么这个目录结构是这样, 原来找不到对应接口的问题就在这!
java目录下的包目录是这样的com下crb下mapper和model
resources目录下目录是这样的com.crb.mapper, 对这个文件夹的全称名字就叫com.crb.mapper这个名字, 它并没有分层
所以导致编译后的target目录下会这样显示, 而不是由于目录相同把xml和接口放到同一目录
resources下正确的目录显示应该是这样的
像上边这样的目录结构, 编译后xml和接口就会放到一起
那么又有一个问题, 正确的分层文件夹是怎么创建的呢?
我这有两种办法, 第二种是我突然想到的, 试了一下, 哈哈哈哈竟然好使, 开心 (如果你有更好的, 麻烦留言通知一下, 谢谢)
- 只创建com目录, 在com目录下创建crb目录, 然后在crb目录下创建mapper (这种最累)
- 一般我们创建整个目录时都会输入
com.crb.mapper
, 那么现在你可以试试com/crb/mapper
这种创建目录的方式
如果不好使, 注意Clean一下
折腾了一上午, 这个办法算是我知道最好用的了, 另外还有同学说改pom.xml文件
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
我没试过这种, 一开始搜索的时候, 感觉问题不在这.
2. There is no getter for property named ‘id’ in ‘class java.lang.Long’
上网搜了一下, 加@Param注解, 能解决
加了这个注解, 配置好了value名称, 确实好了, 但是感觉不是这的问题
找到之后, 没把我气死, 看到下边这个有什么错误吗?
<select id="selectById" resultMap="userMap">
select * from mybatis.sys_user where id = ${id}
</select>
上边那个错误在 ${id} 这, 正确应该是 #{id}
哈哈哈哈哈哈哈隔, 气死我了, 写${} 配置写顺手了, 初学Mybatis, 这是不细心
记录一下.