mybatis 中collection嵌套collection引发的bug

<resultMap id="ParentMap" type="org.example.mybatis.Parent">
    <id column="Id" jdbcType="VARCHAR" property="id" />
    <result column="Name" jdbcType="VARCHAR" property="name" />
    <result column="SurName" jdbcType="VARCHAR" property="surName" />

    <collection property="children"
        javaType="ArrayList" ofType="org.example.mybatis.Child"
        resultMap="ChildMap" columnPrefix="c_"/>    
   
</resultMap>

<resultMap id="ChildMap" type="org.example.mybatis.Child">
    <id column="Id" jdbcType="VARCHAR" property="id" />
    <result column="ParentId" jdbcType="VARCHAR" property="parentId" />
    <result column="Name" jdbcType="VARCHAR" property="name" />
    <result column="SurName" jdbcType="VARCHAR" property="surName" />
    <result column="Age" jdbcType="INTEGER" property="age" />

    <collection property="toys"
        javaType="ArrayList" ofType="org.example.mybatis.Toy"
        resultMap="ToyMap" columnPrefix="t_"/>   

</resultMap>

<resultMap id="ToyMap" type="org.example.mybatis.Toy">
    <id column="Id" jdbcType="VARCHAR" property="id" />
    <result column="ChildId" jdbcType="VARCHAR" property="childId" />
    <result column="Name" jdbcType="VARCHAR" property="name" />
    <result column="Color" jdbcType="VARCHAR" property="color" />
</resultMap>

<sql id="Parent_Column_List">
    p.Id, p.Name, p.SurName,
</sql>  

<sql id="Child_Column_List">
    c.Id as c_Id, c.ParentId as c_ParentId, c.Name as c_Name, c.SurName as c_Surname, c.Age as c_Age,
</sql>

<sql id="Toy_Column_List">
    t.Id as t_Id, t.Name as t_Name, t.Color as t_Color
</sql>  

<select id="getParent" parameterType="java.lang.String" resultMap="ParentMap" >
    select 
    <include refid="Parent_Column_List"/>
    <include refid="Child_Column_List" />
    <include refid="Toy_Column_List" />
    from Parent p

    left outer join Child c on p.Id = c.ParentId
    left outer join Toy t on c.Id = t.ChildId
    where p.id = #{id,jdbcType=VARCHAR}
</select>

表面来看没有任何问题 实际 查询的child对象中的toys一直是空

类关系介绍:

  • Parent类有属性ArrayList<Child> children
  • Child类有属性ArrayList<Toy> toys
  • Toy是一个普通的类

原因在于:

<collection property="toys"
        javaType="ArrayList" ofType="org.example.mybatis.Toy"
        resultMap="ToyMap" columnPrefix="t_"/>   

columnPrefix配置的是t_实际mybatis处理后是 c_t_

解决办法:只需要修改 sql 修改前缀为 c_t_ 即可

<sql id="Toy_Column_List">
    t.Id as c_t_Id, t.Name as c_t_Name, t.Color as c_t_Color
</sql>  

 

### 回答1: MyBatisCollection多层嵌套可以通过使用<collection>标签来实现。每一层都可以使用<collection>标签,并且可以通过select属性指定查询语句。例如: ``` <resultMap id="nestedResultMap" type="Parent"> <id property="id" column="id"/> <result property="name" column="name"/> <collection property="children" ofType="Child"> <id property="id" column="child_id"/> <result property="name" column="child_name"/> <collection property="grandchildren" ofType="Grandchild"> <id property="id" column="grandchild_id"/> <result property="name" column="grandchild_name"/> </collection> </collection> </resultMap> <select id="selectNested" resultMap="nestedResultMap"> SELECT * FROM parent LEFT JOIN child ON parent.id = child.parent_id LEFT JOIN grandchild ON child.id = grandchild.child_id </select> ``` 希望这个回答对您有帮助! ### 回答2: Mybatis是一个Java持久层框架,它支持ORM方式,通过XML或注解的配置方式,将关系数据库的数据映射到Java对象,同时提供了灵活的SQL编写方式,使得开发者可以灵活地进行自定义SQL操作。 在MybatisCollection多层嵌套是指在一个实体类,如果有某个属性对应的数据库列是一个集合或数组类型,则可以通过MybatisCollection标签来实现该属性的映射。同样,如果这个集合或数组的元素也是一个实体对象,则可以通过在Collection标签再次使用Mybatis的Nested-select标签来实现多层嵌套的映射。 例如,一个学生有多个选课记录,每个选课记录又包含一个课程和教师信息。如果我们要把这些信息映射到Java对象,则可以定义一个Student实体对象,其包含一个名为courses的集合属性,courses的元素是一个Course对象,Course对象又包含一个Teacher对象。 在映射配置文件,我们可以使用Collection标签来映射这个courses属性,同时可以在Collection标签再次使用Nested-select标签来映射Course对象的teacher属性。具体的配置方式如下: ``` <resultMap id="studentMap" type="Student"> <result property="id" column="id" /> <result property="name" column="name" /> <collection property="courses" ofType="Course"> <result property="id" column="course_id" /> <result property="name" column="course_name" /> <nestedSelect select="selectTeacherByCourseId" resultMap="teacherMap" /> </collection> </resultMap> <resultMap id="teacherMap" type="Teacher"> <result property="id" column="teacher_id" /> <result property="name" column="teacher_name" /> </resultMap> <select id="selectStudentById" resultMap="studentMap"> select * from student where id = #{id} </select> <select id="selectTeacherByCourseId" resultMap="teacherMap"> select * from teacher where id in ( select teacher_id from course_teacher where course_id = #{id} ) </select> ``` 通过这种方式,我们就可以轻松地实现多层嵌套的属性映射,使得实体类的属性可以与数据库的多个表关联,提高了数据查询和操作的灵活性。 ### 回答3: MyBatis是一个流行的Java持久化框架,在操作数据库时提供了方便和灵活性。当我们需要操作具有多层嵌套结构的数据时,MyBatiscollection标签就派上了用场。 collection标签有以下属性: - property:指定属性名称; - ofType:指定集合元素的类型; - select:指定关联查询的SQL语句; - resultMap:指定结果映射的ID; - javaType:指定Java类型; - column:指定表的列名。 由于MyBatiscollection标签有那么多属性,所以有时可能会感到混乱。在多层嵌套结构,我们需要按照我们的需求设置标签的属性。 假设我们有一个宠物店应用程序,其包含如下实体类: ```java public class Pet { private Long id; private String name; private String breed; private List<Toy> toys; // 省略getter和setter方法 } public class Toy { private Long id; private String name; // 省略getter和setter方法 } ``` 我们需要从数据库获取所有宠物和每个宠物所拥有的玩具。在这种情况下,我们需要使用collection标签。 ```xml <!-- 查询所有的宠物和联合查询玩具 --> <select id="getAllPets" resultMap="petResultMap"> SELECT p.id, p.name, p.breed, t.id AS toy_id, t.name AS toy_name FROM pet p LEFT JOIN toy t ON t.pet_id = p.id </select> <!-- 配置resultMap --> <resultMap id="petResultMap" type="Pet"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="breed" column="breed"/> <!-- 用collection标签映射pet有many的toy集合 --> <collection property="toys" ofType="Toy" resultMap="toyResultMap"/> </resultMap> <resultMap id="toyResultMap" type="Toy"> <id property="id" column="toy_id"/> <result property="name" column="toy_name"/> </resultMap> ``` 在上面的示例,我们定义了两个resultMap来映射查询结果。 petResultMap将查询到的数据映射到Pet实体类,并使用collection标签映射每个Pet对象的toys属性为一个玩具列表。```ofType="Toy"```属性告诉MyBatis将toys属性映射为Toy对象的列表。Collection标签resultMap属性设置为```toyResultMap```告诉MyBatis将查询结果映射到Toy对象上。 以上就是MyBatis collection多层嵌套的简单介绍。深入理解和熟练掌握这个标签不仅可以让我们更好地利用MyBatis操作数据,而且可以提高我们的编码效率。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值