前提
总结这个文章的前提是要会基本的SQL语句(我用的MySQL)和JDBC的基本实现。在这个基础上,我们可以通过一些标签或者注解去实现对数据库的多表联查基于一对一和一对多的关系。
第二点,我们在制作数据库时一定要考虑不同的表之间的关系。这种关系指的就是一对一和一对多的关系,举个例子,一个班有许多学生但一个学生不会在不同班上课,因此班级——>学生就是一对多,而学生——>班级就是一对一。
在理解以上两点后,我们就可以去用Mybatis去实现多表联查。
注解去实现联查
首先,我们建立一个基于mybatis框架的项目,具体的目录如图
整个项目中,我们需要完成实体类的包,Dao层的包以及Mapper包去放我们的接口,我展示了实体类和Dao层接口。
Dao层接口
在Dao层接口中,我们需要写一个实现增删改查等数据库操作的接口,那么mybatis会在我们调用这些接口时,自动帮我们去创建实现类然后去实现这些接口。用注释的方法来传输我们的SQL语句,一些关键字是我们需要知道的:insert, delete, update,select。这四个关键字是最重要的,以上是在单表查询需要知道的关键字,如果是多表联查,我们需要在这些关键字的基础上了解一下其它关键字
然后是测试
多表联查的映射关系
resultType可以把查询结果封装到pojo类型中,但必须pojo类的属性名和查询到的数据库表的字段名一致。
如果sql查询到的字段与pojo的属性名不一致,则需要使用resultMap将字段名和属性名对应起来,进行手动配置封装,将结果映射到pojo中
resultMap
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
先在Mapper文件中,配置基本的sql语句
<!-- 查询所有的订单数据 -->
<!-- resultMap:填入配置的resultMap标签的id值 -->
<select id="selectAll" resultMap="studentMap">
select * from student
</select>
配置resultMap标签,映射不同的字段和属性名
<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
<!-- id:设置ResultMap的id -->
<resultMap id="studentMap" type="com.ye.bean.Student">
<!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
<!-- property:主键在pojo中的属性名 -->
<!-- column:主键在数据库中的列名 -->
<id property="id" column="id" />
<!-- 定义普通属性 -->
<association property="classInfo"
select="com.ye.dao.ClassInfoDao.selectByCid" column="cid"/>
</resultMap>
结果就可以封装到pojo类型中
使用resultMap进行关联查询
一对一查询
配置Mapper.xml配置文件
OrderMapper.xml
先使用id和result属性,映射order类的结果集,然后在使用association映射关联对象User的结果集
<resultMap id="studentMap" type="com.ye.bean.Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="sex" column="sex"/>
<result property="phone" column="phone"/>
<result property="address" column="address"/>
<
<!-- association :配置一对一属性 -->
<!-- property:order里面的User属性名 -->
<!-- javaType:属性类型 -->
<association property="classInfo" select="com.ye.dao.ClassInfoDao.selectByCid" column="cid"/>
</resultMap>
<!-- 一对一关联,查询订单,订单内部包含用户属性 -->
<select id="selectAll" resultMap="studentMap">
select * from student
</select>
测试
@Test
public void selectAdd(){
List<Student> students = student.selectAll();
for (Student student1 : students) {
System.out.println(student1);
}
}
动态SQL
可以根据具体的参数条件,来对SQL语句进行动态拼接。
比如在以前的开发中,由于不确定查询参数是否存在,许多人会使用类似于where 1 = 1 来作为前缀,然后后面用AND拼接要查询的参数,这样,就算要查询的参数为空,也能够正确执行查询,如果不加1 = 1,则如果查询参数为空,SQL语句就会变成SELECT * FROM student where,SQL不合法。
mybatis里的动态标签主要有:if 当满足test条件时,才会将<if>标签内的SQL语句拼接上去。
where <where>标签只会在至少有一个子元素返回了SQL语句时, 才会向SQL语句中添加WHERE,并且如果WHERE之后是以AND或OR开头,会自动将其删掉。
//模糊查询
<select id="seach" parameterType="student" resultMap="studentMap">
select * from student
<where>
<if test="sname!=null and sname!=''">
or sname like concat('%',#{sname},'%')
</if>
<if test="sex!=null and sex!=''">
or sex like concat('%',#{sex},'%')
</if>
<if test="phone!=null and phone!=''">
or phone like concat('%',#{phone},'%')
</if>
<if test="address!=null and address!=''">
or address like concat('%',#{address},'%')
</if>
</where>
</select>
</select>在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加SET
,并且如果SET之后是以,
开头的话,会自动将其删掉
//修改
<update id="update" parameterType="student">
update student
<set>
<if test="sname!=null and sname!=''">
sname=#{sname},
</if>
<if test="sex!=null and sex!=''">
sex=#{sex},
</if>
<if test="phone!=null and phone!=''">
phone=#{phone},
</if>
<if test="address!=null and address!=''">
address=#{address},
</if>
</set>
where sid=#{sid}
</update>
测试模糊查询
@Test
public void seach(){
Student st=new Student();
st.setSname("李");
st.setAddress("郑");
List<Student> seach = student.seach(st);
System.out.println(seach);
}
结果
对多的关键标签是:<association></association>,这个标签里写的是副表的映射,一般一对多我们是要想清楚谁作为主表的,也就是一对多中的“一”, 这样的数据也会更清晰。
总结
Mybatis的多表联查是十分重要的内容,因为我们的客户需求很多时候我们是需要将两个表结合在一起比如购物车系统,所以我们需要先理清表与表之间的关系,然后选择合适的方式去进行多表联查。