这里说点题外话,网上找的那些资料真的坑,问题和答案牛头不对马嘴,到处复制粘贴,都没有回答到点子上,气死人了!!!这里我对自己目前所遇到的问题做一个总结
一、为什么会出现上面这种情况?
其实出现这个情况的原因是因为使用了错误的属性名称,要么是因为你的拼写真的写错了(大写的滑稽),要么就是因为你使用了错误的传参
二、大家在使用嵌套查询,遇到<collection> <association>需要传参的时候,怎么办呢?简单啊,column="colField",然后到子查询去取??什么鬼?怎么运作的?
在嵌套标签中,column="colField"其实只是面向一个参数的简写,当父查询向子查询只传递一个参数的时候,就可以这么写,就像框架中,接口方法只有一个参数的时候,可以省略掉@Param注解一样。本质上,column="colField"的格式应该是 column="property=colField",property是指你的参数传递到子查询后的参数名称,colField是父查询中映射出来的column的值,也就是<result column="" property="">中的column中查询得到的值。
那么,如果简写了呢,简写了就没有property了呀?子查询怎么取值呢?如果进行了简写,默认会使用父查询个中的<result column="" property="">中的property进行映射,但是子查询校验中不能使用property != null来校验,具体校验方式看后面,我测出来结果是这样,源码由于时间原因没有去读。
PS:单个参数的传递方式,可以使用column="colField"或者column="property=colField"进行传值
我们再来说说多个参数的传值,触类旁通,多个参数的传值可以通过column="co1,co2,co3"或者column="pro1=co1,pro2=co2,pro3=co3"吗?当然是不行的,
PS:多个参数的传值只能用后者的写法:column="pro1=co1,pro2=co2,pro3=co3",没有道理!!
说完了传值,我们再来看看取值,这里取值就有意思了,针对<if test="">的校验判断和#{ }
取值其实也是差不多的,我总结了一下取值的方式:
1.column="xxx"传一个值:使用_paramete、数字0位置索引进行<if>校验,使用_paramete、数字0位置索引和父查询property进行SQL条件拼接
2.column="xxx,xxx,xxx"传多个值:没成功过!!!!
3.column="prop=col"传一个值:使用_paramete、数字0位置索引、prop进行<if>校验,使用_paramete、数字0位置索引或prop进行SQL条件拼接
4.column="pro1=co1,pro2=co2,pro3=co3"传多个值:使用_paramete.get(数字位置索引)、数字位置索引、prop进行<if>校验,使用_paramete.get(数字位置索引)、数字位置索引或prop进行SQL条件拼接
三、下面附上测试用的xml
<select id="findList" resultMap="teacherMap">
select id,name as myName, update_time as time from tb_teacher
</select>
<select id="findStudent" resultType="com.fengwuJ.entity.Student">
select * from tb_student
<where>
<!--<if test="0 != null">and name = #{name}</if>-->
<if test="0 != null">and id != #{id}</if>
</where>
</select>
<!--教师表,一个教师有下有一个学校信息和多个学生-->
<!--column:数据库字段名一般和数据库字段名相同,也可以是select语句中起的别名-->
<!--property:实体的属性名字,通过Map配置进行关系映射-->
<resultMap id="teacherMap" type="com.fengwuJ.entity.Teacher">
<id column="id" property="id" />
<result column="myName" property="name" />
<result column="time" property="updateTime"/>
<!--<association>一对一实体引用映射标签-->
<!--javaType:指定该引用的类型,实测可以不指定,mybatis应该可以自动推断-->
<!--property:指定属性名称-->
<!--column:嵌套查询传参,传参格式:
1.参数名称=列名称,参数名称:传到子查询sql的参数名称,子查询中通过#{参数名称}取值,列名称:实际代表父查询中当前行该列的值
2.直接写列名称(只能用于一个参数),会默认使用父查询的result或id进行property=column构造,通过mybatis内置对象_parameter取参,当只有一个参数时,在<if test="">使用_parameter进行判断,使用#{_parameter}取值
当有多个参数时,使用_parameter.get(0)进行判断,使用#{_parameter.get(0)}取值,或者使用0,1,2的参数位置判断,使用#{0}取值
总结:在子查询中使用<if>的,可以通过_parameter(单个参数),_parameter.get(0/1/2....)(多个参数),直接使用位置下标0,1,2,或者使用property名称(自定义的,或者父查询定义的)
在子查询中使用#{}取值的,可以通过#{_parameter},#{_parameter.get(0/1/2...)},#{0/1/2...},#{property(自定义或默认使用父查询的property)}-->
<!--<association javaType="com.fengwuJ.entity.Student" property="student" column="myName,id" select="findStudent">
</association>-->
<!--<collection> 一对多List<Model>映射标签-->
<!--ofType:List<Model> 中 Model实体的类型-->
<!--其余同上,经测,ofType也可以不用写,暂时不明原因-->
<collection property="students" ofType="com.fengwuJ.entity.Student" column="id=id" select="findStudent"></collection>
</resultMap>
补充一句:如果是使用select查询,ofType和javaType可以不用配置,如果使用where连表查询,就需要配置这两个东西了,还有就是,一对一关系建议连表,一对多关系建议使用子查询,但需要把子查询的条件筛选想办法转移到主表中,这样可以解决条件分页问题。
最后还有一点,是关于mybatis和tk.mapper的。这两个既有关系也没关系。tk.mapper主要用的是单表,一般配合PageHelper进行单表的分页查询,tk.mapper的映射主要是通过Model实体@Column注解映射,不使用注解则会进行自动映射,必须要是数据库的字段才行,因为数据库操作被tkmapper做完了,没办法为字段起别名,PageHelper则是实现了mybatis的拦截器。而mybatis的映射,一是自动映射,而则是使用resultMap映射,resultMap中,<result column="" property="">,在这个标签中,column指的是select查出来的字段名,如果取了别名就使用别名,没取别名就使用数据库的字段名,和@Column注解没有什么关系,property则是只该字段要映射到的实体的属性名字。
收获还是有的,就是时间花得多,,,我也只是简单的测了下,大家遇到问题了欢迎反馈,一起交流