最近学习mybatis框架时,遇到一坑,记录一下debug过程。
操作表一对一查询时,运行junit测试类时报错如下:
org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in com/annoDemo/dao/IAccountDao.xml
### The error occurred while processing mapper_resultMap[accountUserMap]
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'com/annoDemo/dao/IAccountDao.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'account'. Cause: java.lang.ClassNotFoundException: Cannot find class: account
根据错误提示,第一时间检查了mapper的xml文件名称以及对应的包名是否跟dao接口类的一致,确认没有问题后,初步判定原因是mapper映射文件问题,mapper内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 配置对应dao接口 -->
<mapper namespace="com.annoDemo.dao.IAccountDao">
<resultMap id="accountUserMap" type="account">
<id property="id" column="aid" />
<result property="uid" column="uid" />
<result property="money" column="money" />
<!-- 基于从表外键的 一对一映射 -->
<association property="user" column="uid" javaType="user">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="sex" column="sex" />
<result property="address" column="address"/>
</association>
</resultMap>
<select id="listAccounts" resultMap="accountUserMap" >
select a.id as aid,a.uid,a.money,u.* from account a ,user u where a.uid = u.id;
</select>
</mapper>
随后检查mapper文件中返回类型以及实体类属性、数据表对应字段,发现应该是由于resultMap定义的返回类型有问题,于是检查mybatis主配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入Mybatis的xml约束 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的主配置文件-->
<configuration>
<!-- 从外部配置文件读连接信息 -->
<properties resource="JdbcConfig.properties"></properties>
<!-- 配置id为mysql的环境配置-->
<environments default="mysql">
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(POOLED连接池)-->
<dataSource type="POOLED">
<!-- 配置四个数据库的基本信息 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- package指定dao接口所在包,mapper中可以不需要写全限定类名,就不用写resource和class了 -->
<package name="com.annoDemo.dao" />
</mappers>
</configuration>
果不其然,调试后明确问题:
由于主配置文件只配置了<mappers>标签下的<package>指定了dao接口所在包,没有配置<typeAliases>下的<package>指定实体类的别名,因此mapper文件中返回的实体类名称不能使用简写,需要写完整全限定类名
<!-- 配置别名 -->
<typeAliases>
<!-- 配置实体类的别名,mapper内可以不写实体类全类型,别名默认为类名 -->
<package name="com.annoDemo.domain"/>
</typeAliases>
主配置文件指定实体类别名后测试,测试类正常返回一对一查询的数据