需求场景:联表查询时存在一对多映射需求,且对应的是内部类映射。
Mybatis_Plus映射内部类集合的时候,服务启动就报错,话不多说直接上报错内容:
Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'cn.cooper.domain.Teacher.Student'. Cause: java.lang.ClassNotFoundException: Cannot find class: cn.cooper.domain.Teacher.Student
at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:120) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.builder.BaseBuilder.resolveAlias(BaseBuilder.java:149) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:116) ~[mybatis-3.5.5.jar:3.5.5]
... 60 common frames omitted
Caused by: java.lang.ClassNotFoundException: Cannot find class: cn.cooper.domain.Teacher.Student
at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:200) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:89) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.io.Resources.classForName(Resources.java:261) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:116) ~[mybatis-3.5.5.jar:3.5.5]
... 62 common frames omitted
接下来是我的SQL语句:
<select id="list" resultMap="resultMap">
SELECT
t.id tid,
t.`name` tname,
s.id sid,
s.`name` sname
FROM
teacher t
LEFT JOIN student s ON s.teacher_id = t.id
</select>
<resultMap id="resultMap" type="cn.cooper.domain.Teacher">
<result column="tid" property="id"></result>
<result column="tname" property="name"></result>
<collection property="students" ofType="cn.cooper.domain.Teacher.Student">
<result column="sid" property="id"></result>
<result column="sname" property="name"></result>
</collection>
</resultMap>
Java实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("teacher")
public class Teacher {
private Long id;
private String name;
private List<Student> students;
@Data
public static class Student {
private Long id;
private String name;
}
}
表设计SQL:
CREATE TABLE `teacher` (
`id` bigint(12) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `student` (
`id` bigint(12) NOT NULL,
`name` varchar(32) DEFAULT NULL,
`teacher_id` bigint(12) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
好的,回到报错内容:实体类中内部类的Student类找不到,但是写法好像没问题。查阅了一些资料,发现原因在于包名:映射的时候不是使用.(点)表示内部类关系,而是使用的$
解决方案如下:
<!--错误写法-->
<collection property="students" ofType="cn.cooper.domain.Teacher.Student">
<result column="sid" property="id"></result>
<result column="sname" property="name"></result>
</collection>
<!--正确写法-->
<collection property="students" ofType="cn.cooper.domain.Teacher$Student">
<result column="sid" property="id"></result>
<result column="sname" property="name"></result>
</collection>
再次启动就没问题了
2022-09-14 20:09:14.792 INFO 10492 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.31]
2022-09-14 20:09:14.871 INFO 10492 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-09-14 20:09:14.871 INFO 10492 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 858 ms
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.4.0
2022-09-14 20:09:15.561 INFO 10492 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2022-09-14 20:09:15.762 INFO 10492 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 80 (http) with context path ''
2022-09-14 20:09:15.765 INFO 10492 --- [ main] cn.cooper.App : Started App in 2.203 seconds (JVM running for 3.149)
尝试访问:
[
{
"id": 1,
"name": "张三",
"students": [
{
"id": 1,
"name": "撒大声地"
},
{
"id": 2,
"name": "啊实打实"
}
]
},
// 多余结果省略.....
]
虽然只是一个很小的知识点,但是也希望能帮助到查找的人