多对一、一对多的使用示例;动态SQL语句;
多对一、一对多的使用示例
创建一对多数据库
## 一对多数据表
## 创建班级表
create table t_clazz(
`id` int primary key auto_increment,
`name` varchar(50)
);
## 插入班级信息
insert into t_clazz(`name`) values('javaEE20170228');
insert into t_clazz(`name`) values('javaEE20170325');
insert into t_clazz(`name`) values('javaEE20170420');
insert into t_clazz(`name`) values('javaEE20170515');
## 创建学生表
create table t_student(
`id` int primary key auto_increment,
`name` varchar(50),
`clazz_id` int,
foreign key(`clazz_id`) references t_clazz(`id`)
);
## 插入班级信息
insert into t_student(`name`,`clazz_id`) values('stu0228_1',1);
insert into t_student(`name`,`clazz_id`) values('stu0228_2',1);
insert into t_student(`name`,`clazz_id`) values('stu0228_3',1);
insert into t_student(`name`,`clazz_id`) values('stu0325_1',2);
insert into t_student(`name`,`clazz_id`) values('stu0325_2',2);
insert into t_student(`name`,`clazz_id`) values('stu0420_1',3);
一对多,立即加载
创建student类
public class Student {
private Integer id;
private String name;
创建Clazz类
public class Clazz {
private Integer id;
private String name;
private List<Student> stus;
ClazzMapper接口
public interface ClazzMapper {
/**
* 根据班级id的信息,直接查询出班级信息,以及这个班的全部学生信息。
*/
public Clazz queryClazzByIdForSample(Integer id);
}
ClazzMapper.xml配置文件:
collection 标签是专门用来配置集合属性的标签
- property属性设置你要配置哪个集合属性
- ofType 属性设置这个集合中每个元素的具体类型
<?xml version=”1.0” encoding=”UTF-8” ?> <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd”>
<mapper namespace="com.ncu.zte.mybatis6_29.mapper.ClazzMapper">
<resultMap type="clazz" id="queryClazzByIdSample_resultMap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="stus" ofType="student">
<id column="stu_id" property="id"/>
<result column="stu_name" property="name"/>
</collection>
</resultMap>
<!-- * 根据班级id的信息,直接查询出班级信息,以及这个班的全部学生信息。 -->
<select id="queryClazzByIdSample" resultMap="queryClazzByIdSample_resultMap">
SELECT t_clazz.*,t_student.id stu_id,t_student.`name` stu_name
FROM t_clazz LEFT JOIN t_student ON t_clazz.`id` = t_student.`clazz_id`
WHERE t_clazz.`id` = 2
</select>
</mapper>
测试代码:
@Test
public void testQueryClazzByIdSample() throws IOException {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("com/ncu/zte/mybatis6_29/mybatis-config.xml"));
SqlSession session =sqlSessionFactory.openSession();
try{
ClazzMapper mapper = session.getMapper(ClazzMapper.class);
System.out.println(mapper.queryClazzByIdSample(2));
}finally{
session.close();
}
fail("Not yet implemented");
}
测试结果
一对多,赖加载
ClazzMapper接口
/**
* 根据班级id查询班级信息(只查班级)
*/
public Clazz queryClazzByIdForTwoStep(Integer id);
StudentMapper接口
public interface StudentMapper {
/**
* 根据班级编号查询本班所有学生信息
*/
public List<Student> queryStudentsByClazzId(Integer clazzId);
}
StudentMapper.xml配置文件
<mapper namespace="com.ncu.zte.mybatis6_29.mapper.StudentMapper">
<!-- * 根据班级编号查询本班所有学生信息 -->
<select id="queryStudentByClazzId" resultType="student">
select id,name from t_student where clazz_id =#{clazzId}
</select>
</mapper>
ClazzMapper.xml配置文件
collection 标签是专门用来配置集合属性的(它可以通过调用一个select查询得到需要集合)。
- property属性设置你要配置哪个集合属性
- select 属性设置你要调用哪个查询
- column 将哪个列的值传递给查询做为参数
<resultMap type=”clazz” id=”queryClazzByIdForTwo_resultMap”>
<id column="id" property="id"/\>
<result column="name" property="name"/\>
<collection property="stus" column="id" select="com.ncu.zte.mybatis6_29.mapper.StudentMapper.queryStudentByClazzId" \></collection\>
</resultMap>
<!-- * 根据班级id查询班级信息(只查班级) --\>
<select id="queryClazzByIdForTwo" resultMap="queryClazzByIdForTwo_resultMap"\>
select id,name from t_clazz where id = #{id}
<select\>
测试代码
只查班级信息:
@Test
public void queryClazzByIdForTwo() throws IOException {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("com/ncu/zte/mybatis6_29/mybatis-config.xml"));
SqlSession session =sqlSessionFactory.openSession();
try{
ClazzMapper mapper = session.getMapper(ClazzMapper.class);
Clazz clazz = mapper.queryClazzByIdForTwo(1);
System.out.println(clazz.getId()+clazz.getName());
System.out.println(clazz.getStus());
}finally{
session.close();
}
fail("Not yet implemented");
}
查询班级中student信息
System.out.println(clazz.getStus());
双向关联
StudentMapper接口
/**
* 把学生分两次查,一次还要查班级。
*/
public List<Student> queryStudentsByClazzIdForTwoStep(Integer clazzId);
StudentMapper.xml配置文件:
<resultMap type="student" id="queryStudentByClassIdForTwo_resultMap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="clazz" column="clazz_id" select="com.ncu.zte.mybatis6_29.mapper.ClazzMapper.queryClazzByIdForTwo">
</collection >
</resultMap>
<select id="queryStudentByClassIdForTwo" resultMap="queryStudentByClassIdForTwo_resultMap">
select id,name,clazz_id from t_student where clazz_id = #{clazzId}
</select>
还要修改ClazzMapper.xml配置文件:
<select id="queryClazzByIdForTwo" resultMap="queryClazzByIdForTwo_resultMap"\>
select id,name from t_clazz where id = #{id}
</select\>
测试
@Test
public void queryStudentByClassIdForTwo() throws IOException {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("com/ncu/zte/mybatis6_29/mybatis-config.xml"));
SqlSession session =sqlSessionFactory.openSession();
try{
ClazzMapper mapper = session.getMapper(ClazzMapper.class);
Clazz clazz = mapper.queryClazzByIdForTwo(1);
List<Student> stus = clazz.getStus();
for(Student student :stus){
System.out.println(student.getId()+" "+student.getName()+" "+student.getClazz().getName());
}
}finally{
session.close();
}
fail("Not yet implemented");
}
双向关联的常见问题:死循环。
如何解决双向关联的死循环: 方法一:不要调用toString方法。 方法二:在你需要终止调用的最后一次查询使用resultType,而不用resultMap
动态SQL语句
if 语句
说明: if语句,可以动态的根据你的值来决定,是否需要动态的添加查询条件。
UserMapper接口
public interface UserMapper {
/**
* 根据user对象中的lastName和sex属性查询用户 <br/>
* 希望lastName值不能为null,
* 性别只能是0和1,有效值
*
* @param user
* @return
*/
public List<User> queryUsersByNameAndSex(User user);
}
UserMapper.xml配置文件:
<!-- /** -->
<!-- * 根据user对象中的lastName和sex属性查询用户 -->
<!-- * -->
<!-- * @param user -->
<!-- * @return -->
<!-- */ -->
<!-- public List<User> queryUsersByNameAndSex(User user); -->
<select id="queryUsersByNameAndSex" resultType="com.atguigu.pojo.User">
select
id,last_name lastName,sex
from
t_user
where
<if test="lastName != null">
last_name like concat('%',#{lastName},'%')
</if>
<if test="sex == 0 || sex == 1">
and sex = #{sex}
</if>
</select\>
where 语句
说明: where语句,可以帮我们在多个动态语句中,有效的去掉前面的多余的and 或 or 之类的多余关键字,比如上面的if语句中,如果前一个判断为false,则语句就变成了where and sex = ${sex},自然就会出错
<select id="queryUsersByNameAndSex" resultType="com.atguigu.pojo.User">
select
id,last_name lastName,sex
from
t_user
<!-- where标签可以动态的去掉包含的内容前面的关键字and 和 or
where 标签还会在包含的内容有的情况,添加一个where关键字
-->
<where>
<!-- if标签用来判断一个条件是否成立。如果成立 就执行里面的内容 -->
<if test="lastName != null">
last_name like concat('%',#{lastName},'%')
</if>
<if test="sex == 0 || sex == 1">
and sex = #{sex}
</if>
</where>
</select>
trim语句
说明: trim 可以动态在包含的语句前面和后面添加内容。也可以去掉前面或者后面给定的内容,比如上面的if语句中,如果后一个判断为false,则语句就变成了where last_name like concat(‘%’,’bb’,’%’) ,自然就会出错
- prefix 前面添加内容
- suffix 后面添加内容
- suffixOverrides 去掉的后面内容
-
prefixOverrides 去掉的前面内容
<select id=”queryUsersByNameAndSex” resultType=”com.atguigu.pojo.User”> select id,last_name lastName,sex from t_user
<!-- where标签可以动态的去掉包含的内容前面的关键字and 和 or where 标签还会在包含的内容有的情况,添加一个where关键字 --> <trim suffixOverrides="and" prefix="where"> <!-- if标签用来判断一个条件是否成立。如果成立 就执行里面的内容 --> <if test="lastName != null"> last_name like concat('%',#{lastName},'%') and </if> <if test="sex == 0 || sex == 1"> sex = #{sex} </if> </trim> </select>
choose( when , otherwise )语句
说明:choose when otherwise 可以执行多路选择判断,但是只会有一个分支会被执行。
类似switch case 语句
UserMapper接口
/**
* 如果lastName有值,则使用它查询
* 如果lastName没有值,sex值有效,则使用sex查询
* 否则,你自己添加一个查询条件(默认)
*/
public List<User> queryUsersByNameAndSexChoose(User user);
UserMapper.xml配置文件:
<select id="queryUsersByNameAndSexChoose" resultType="com.atguigu.pojo.User">
select
id,last_name lastName,sex
from
t_user
<where>
<choose>
<when test="lastName != null">
last_name like concat('%',#{lastName},'%')
</when>
<when test="sex == 0 || sex == 1">
sex = #{sex}
</when>
<otherwise>
last_name = 'wzg168'
</otherwise>
</choose>
</where>
</select>
set语句
删除条件后的逗号
UserMapper接口
public int updateUser(User user);
UserMapper配置文件:
<update id="updateUser" parameterType="com.atguigu.pojo.User">
update
t_user
<set>
<if test="lastName != null">
last_name = #{lastName},
</if>
<if test="sex == 0 || sex == 1">
sex = #{sex}
</if>
</set>
where
id = #{id}
</update>
foreach语句
select * from t_user where id in (1,3,4);
UserMapper接口
/**
* 执行类似的语句:select * from t_user where id in (1,3,4);
*/
public List<User> queryUsersByIds(List<Integer> ids);
UserMapper配置文件:
<!-- /** -->
<!-- * 执行类似的语句:select * from t_user where id in (1,3,4); -->
<!-- */ -->
<!-- public List<User> queryUsersByIds(List<Integer> ids); -->
<select id="queryUsersByIds" resultType="com.atguigu.pojo.User">
select
id,last_name lastName,sex
from
t_user
<where>
id in
<!--
foreach 遍历输出
collection你要遍历的数据源
items 表示当前遍历的数据
open 表示遍历之前添加的内容
close 表示遍历之后添加的内容
separator 给遍历的每个元素中间添加的内容
-->
<foreach collection="list" item="i" open="(" close=")" separator=",">
#{i}
</foreach>
</where>
</select>