MyBatis学习笔记二:MyBatis增删改查等映射操作
映射文件的增删改查(mapper.xml)
1.建立mapper映射文件
<?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="dao.DeptMapper">
<!--接口返回类型定义区-->
<!--接口方法对应的sql语句写入-->
2. 基本增删改查语句
MyBatis获取参数值的两种方式:${}和#{}
${}
的本质就是字符串拼接(类似宏定义,不会有多余的字符修饰),#{}
的本质就是占位符赋值(会根据类型变化,字符串类型会在填充时加上单引号)
在获取的参数值使用场景中:
如果是字符类型可以使用#{}
和'${}'
两种方式
如果是数值型可以使用#{}
和${}
两种方式
<!--接口中的方法 @Param("did"):占位符键值,占位符根据键将对应的形参值传进sql语句-->
- 增加数据
<!--
public boolean save(User user);
public boolean save(Map<String,Object> map); //将每条属性写成键值对的形式
public boolean save(@Param("username") String username, @Param("password") String password, @Param("age") int age, @Param("sex") sex, @Param("email") String email);
-->
<insert id="save">
insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
- 删除数据
<!--
public boolean deleteById(@Param("id") Integer id);
-->
<delete id="deleteById">
delete from t_user where id = #{id}
</delete>
- 修改数据
<!--
public boolean update(User user);
-->
<update id="update">
update t_user set username = #{username},password = #{password},age = #{age},sex = #{sex},email = #{email} where id = #{id}
</update>
- 查询单个数据
<!-- resultType是返回值类型
1.自定义的类需要写进返回值类型,简写需要在核心配置文件的配置文件里面导入,否则要写全类名
2.非自定义的基本类型可以不写(int double Integer等)
3.其他 Map--map,List--list
-->
<!--public Dept getDeptById(@Param("did") Integer did)-->
<select id="getDeptById" resultType="Dept">
select * from t_dept where did = #{did}
</select>
<!--返回类型为list,map要写-->
<!--Map<String, Object> getUserToMap(@Param("id") int id);-->
<select id="getUserToMap" resultType="map">
select * from t_user where id = #{id}
</select>
- 查询多个数据
<!--
接口定义方式一:
List<Map<String, Object>> getAllUserToMap();
接口定义方式二:
@MapKey("id") //需要指定键值类型
Map<String, Object> getAllUserToMap();
-->
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
3.特殊SQL执行
- 模糊查询
<!--List<User> testMohu(@Param("mohu") String mohu);-->
<select id="testMohu" resultType="User">
<!--select * from t_user where username like '%${mohu}%'-->
<!--select * from t_user where username like concat('%',#{mohu},'%')-->
select * from t_user where username like "%"#{mohu}"%"
</select>
- 批量删除
<!--int deleteMore(@Param("ids") String ids);-->
<delete id="deleteMore">
delete from t_user where id in (${ids})
</delete>
- 动态设置表名
<!--List<User> getAllUser(@Param("tableName") String tableName);-->
<!--表名不能用单引号引用-->
<select id="getAllUser" resultType="User">
select * from ${tableName}
</select>
- 获取自增的主键
<!--自增的主键一般在实体类中不进行赋值,当写入数据库,自然就会生成,如何在不进行二次查询的情况下获取主键-->
<!--int insertUser(User user);-->
<!--
useGeneratedKeys:设置使用自增的主键
keyProperty:因为增删改有统一的返回值是受影响的行数,不能直接写在返回值上
,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{sex})
</insert>
4. SQL查询返回值类型详解
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
<!--
resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系(用于自定义类映射关系)
collection:设置一对多的映射关系(用于自定义类映射关系)
子标签 属性:
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
-->
<resultMap id="userMap" type="User">
<id property="id" column="id"></id>
<result property="userName" column="user_name"></result>
<result property="password" column="password"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</resultMap>
<!--List<User> testMohu(@Param("mohu") String mohu);-->
<select id="testMohu" resultMap="userMap">
<!--select * from t_user where username like '%${mohu}%'-->
select id,user_name,password,age,sex from t_user where user_name likeconcat('%',#{mohu},'%')
</select>
- 使用association,处理多对一关系,(返回多个表属性组成的实例对象)
<resultMap id="empDeptMap" type="Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<!--返回的定义类-->
<association property="dept" javaType="Dept">
<id column="did" property="did"></id>
<result column="dname" property="dname"></result>
</association>
</resultMap>
<!--第二种分布操作-->
<resultMap id="empDeptStepMap" type="Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<!--
select:设置下一步分步查询,查询某个属性的值的sql的标识(namespace.sqlId)
column:将第一步sql查询结果中的某个字段设置为分步查询的条件
-->
<association property="dept"
select="DeptMapper.getEmpDeptByStep"
column="did">
</association>
</resultMap>
<!--Emp getEmpByStep(@Param("eid") int eid);-->
<select id="getEmpByStep" resultMap="empDeptStepMap">
select * from t_emp where eid = #{eid}
</select>
- collection,使用一对多映射关系(返回列表)
<resultMap id="deptEmpMap" type="Dept">
<id property="did" column="did"></id>
<result property="dname" column="dname"></result>
<!--
ofType:设置collection标签所处理的集合属性中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="ename" column="ename"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</collection>
</resultMap>
<!--Dept getDeptEmpByDid(@Param("did") int did);-->
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did =emp.did where dept.did = #{did}
</select>
<!--第二种-->
<!-- fetchType="eager"设置缓存,如果不访问emp集合的内容,所以不加载后面的sql-->
<resultMap id="deptEmpStep" type="Dept">
<id property="did" column="did"></id>
<result property="dname" column="dname"></result>
<collection property="emps"
fetchType="eager"
select="EmpMapper.getEmpListByDid"
column="did">
</collection>
</resultMap>
<!--Dept getDeptByStep(@Param("did") int did);-->
<select id="getDeptByStep" resultMap="deptEmpStep">
select * from t_dept where did = #{did}
</select>
5. SQL条件输入
- if
if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
<select id="getEmpListByMoreTJ" resultType="Emp">
select * from t_emp where 1=1
<if test="ename !='' and ename != null">
and ename = #{ename}
</if>
<if test="age !='' and age != null">
and age = #{age}
</if>
<if test="sex !='' and sex != null">
and sex = #{sex}
</if>
</select>
- where...if
<select id="getEmpListByMoreTJ" resultType="Emp">
select * from t_emp
<!--
若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的
and去掉
-->
<where>
<if test="ename !='' and ename != null">
and ename = #{ename}
</if>
<if test="age !='' and age != null">
and age = #{age}
</if>
<if test="sex !='' and sex != null">
and sex = #{sex}
</if>
</where>
</select>
- trim...if
效果作用于trim标签内部所有if标签判断完成后新生成的拼接字符串的前部和后部
<select id="getEmpListByMoreTJ" resultType="Emp">
select * from t_emp
<!--
prefix:在trim标签中的内容的前面添加某些内容
prefixOverrides:在trim标签中的内容的前面去掉某些内容
suffix:在trim标签中的内容的后面添加某些内容
suffixOverrides:在trim标签中的内容的后面去掉某些内容
-->
<trim prefix="where" suffixOverrides="and">
<if test="ename !='' and ename != null">
ename = #{ename} and
</if>
<if test="age !='' and age != null">
age = #{age} and
</if>
</trim>
</select>
- choose、when、otherwise
相当于if...else if..else(只能选择一个条件)
<select id="getEmpListByChoose" resultType="Emp">
select <include refid="empColumns"/> from t_emp
<where>
<choose>
<when test="ename !='' and ename != null">
ename = #{ename}
</when>
<when test="age !='' and age != null">
age = #{age}
</when>
<otherwise>
<!--都不能满足条件,执行这里-->
</otherwise>
</choose>
</where>
</select>
- foreach
相当于遍历集合中的元素
<delete id="deleteMoreByArray">
delete from t_emp where
<!--
collection:设置要循环的数组或集合
item:表示集合或数组中的每一个数据
separator:设置循环体之间的分隔符
open:设置foreach标签中的内容的开始符
close:设置foreach标签中的内容的结束符
-->
<foreach collection="eids" item="eid" separator="or">
<!--被遍历重复执行的语句-->
eid = #{eid}
</foreach>
</delete>
- 重复的sql语句
sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
<sql id="empColumns">
eid,ename,age,sex,did
</sql>
select <include refid="empColumns"></include> from t_emp