一、映射Mapper
接口方法映射到对应的SQL
XXXMapper.xml的命名空间名称就是Mapper接口的全限定名
Mapper接口上也可以通过相应的注释来写SQL(但是最好不要这么写哦)
// 查询全部
// @Select("select * from employee")
List<Employee> findAll();
employeeMapper.xml
<?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="cn.cxm.mapper.mapper.EmployeeMapper">
<select id="findOne" parameterType="long" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee WHERE id=#{id}
</select>
<select id="findAll" parameterType="long" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee
</select>
<insert id="save" parameterType="cn.cxm.mapper.domain.Employee" >
INSERT INTO employee (name,age) VALUES (#{name},#{age})
</insert>
<!--
<update id="update" parameterType="cn.cxm.mapper.domain.Employee">
UPDATE employee SET name=#{name},age=#{age} WHERE id=#{id}
</update>
-->
<delete id="delete" parameterType="long">
DELETE FROM employee WHERE id=#{id}
</delete>
<!--
添加多条数据
使用foreach标签,collection:遍历的集合,item:集合的每一个元素
separator:分离符
-->
<insert id="batchSave" parameterType="list">
INSERT INTO employee (name,age) VALUES
<foreach collection="list" item="emp" separator=",">
(#{emp.name},#{emp.age})
</foreach>
</insert>
<!--批量删除,删除一定范围,使用in( ,)-->
<delete id="batchDelete" parameterType="list">
DELETE FROM employee WHERE id in
<foreach collection="list" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<!--模糊查询-->
<!--
<select id="queryAll" parameterType="list" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee where name LIKE CONCAT("%",#{name},"%")
</select>
-->
<!--使用where标签,自动将第一个and替换为where-->
<!--多条件查询-->
<select id="queryAll" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="minAge!=null">
AND age>=#{minAge}
</if>
<if test="maxAge!=null">
AND <![CDATA[ age<=#{maxAge}]]>
</if>
</where>
</select>
<!--查询总条数-->
<select id="count" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="long">
SELECT count(id) FROM employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="minAge!=null">
AND age>=#{minAge}
</if>
<if test="maxAge!=null">
AND <![CDATA[ age<=#{maxAge}]]>
</if>
</where>
</select>
<!--动态修改,当使用动态修改,只修改其中的一条数据,同一id的其他数据不会改变-->
<update id="update" parameterType="cn.cxm.mapper.domain.Employee">
UPDATE employee
<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
</set>
WHERE id=#{id}
</update>
</mapper>
EmployeeMapper
package cn.cxm.mapper.mapper;
import cn.cxm.mapper.domain.Employee;
import cn.cxm.mapper.query.EmployeeQuery;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface EmployeeMapper {
// 添加
void save(Employee employee);
// 删除
void delete(Long id);
// 修改
void update(Employee employee);
// 查询一条
Employee findOne(Long id);
// 查询全部
// @Select("select * from employee")
List<Employee> findAll();
// 批量添加
void batchSave(List<Employee> employee);
// 批量删除
void batchDelete(List<Long> id);
// 高级查询之模糊查询
// List<Employee> queryAll(String name);
// 高级查询之多条件查询
List<Employee> queryAll(EmployeeQuery query);
// 查询总条数
Long count(EmployeeQuery query);
}
调用 Mapper的方法
@Test
public void save() throws Exception{
SqlSession session = MybatisUtil.getSession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setName("大蛇丸");
employee.setAge(123);
mapper.save(employee);
session.commit();
}
二.高级查询
准备一个Query对象(封装所有条件)
模糊查询 concat("%",#{name},"%")
遇到特殊符号 1.转义 < 2.CDATA段 <![CDATA[...]]>
使用where标签(第一个and变成where)
if中有多个条件使用 and/or 进行关联
如果出现相就的代码,可以单独抽取sql标签,引用include即可
.employeeMapper.xml
<!--模糊查询-->
<!--
<select id="queryAll" parameterType="list" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee where name LIKE CONCAT("%",#{name},"%")
</select>
-->
<!--使用where标签,自动将第一个and替换为where-->
<!--多条件查询-->
<select id="queryAll" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="cn.cxm.mapper.domain.Employee">
SELECT * FROM employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="minAge!=null">
AND age>=#{minAge}
</if>
<if test="maxAge!=null">
AND <![CDATA[ age<=#{maxAge}]]>
</if>
</where>
</select>
<!--查询总条数-->
<select id="count" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="long">
SELECT count(id) FROM employee
<where>
<if test="name!=null and name!=''">
AND name LIKE CONCAT("%",#{name},"%")
</if>
<if test="minAge!=null">
AND age>=#{minAge}
</if>
<if test="maxAge!=null">
AND <![CDATA[ age<=#{maxAge}]]>
</if>
</where>
</select>
代码片段
<select id="findByQuery" parameterType="employeeQuery" resultType="employee">
select * from employee <include refid="whereSql" />
</select>
<!--准备代码片断-->
<sql id="whereSql">
<where>
<if test="name!=null and name!=''">
and name like concat("%",#{name},"%")
</if>
<if test="minAge!=null">
and age >= #{minAge}
</if>
<if test="maxAge!=null">
<![CDATA[ and age<=#{maxAge} ]]>
</if>
</where>
</sql>
批量删除,添加,动态修改
首先知道sql delete from 表名 where id in (?,?,…)
collection="":代表你要循环的是什么? array/list
如果传过来的是数据,写array(集合就写list)
item:循环的每一个数据
open:拼接字符串以什么开始
close:拼接字符串以什么结尾
separator:拼接的时候每个值使用,隔开
index:遍历的下标
动态修改
<!--动态修改,当使用动态修改,只修改其中的一条数据,同一id的其他数据不会改变-->
<update id="update" parameterType="cn.cxm.mapper.domain.Employee">
UPDATE employee
<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
</set>
WHERE id=#{id}
</update>
批量删除
<!--批量删除,删除一定范围,使用in( ,)-->
<delete id="batchDelete" parameterType="list">
DELETE FROM employee WHERE id in
<foreach collection="list" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
批量添加
<!--
添加多条数据
使用foreach标签,collection:遍历的集合,item:集合的每一个元素
separator:分离符
-->
<insert id="batchSave" parameterType="list">
INSERT INTO employee (name,age) VALUES
<foreach collection="list" item="emp" separator=",">
(#{emp.name},#{emp.age})
</foreach>
</insert>
多对一
准备两张表product、productdir,两个domain,两个mapper.xml
查询(嵌套结果:一条SQL,嵌套查询:多条SQL)
准备domain
product
private Long id;
private String name;
// private Long dirId;
private Double salePrice;
private String supplier;
private String brand;
private Double cutoff;
private Double costPrice;
private Productdir productdir;
//... getter,setter与toString
productdir
private Long id;
private String name;
//... getter,setter与toString
嵌套结果
查询的sql要关连多张表(一定要取别名,不然有些名称会产生冲突)
当我们使用了association 后默认的映射失败,需要自己手动完成映射
<?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="cn.cxm.many2one.mapper.ProductMapper">
<!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
<resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
<id property="id" column="id"/>
<result property="name" column="productName"/>
<result property="salePrice" column="salePrice"/>
<result property="supplier" column="supplier"/>
<result property="brand" column="brand"/>
<result property="cutoff" column="cutoff"/>
<result property="costPrice" column="costPrice"/>
<!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
<association property="productdir" javaType="cn.cxm.many2one.domain.Productdir">
<id property="id" column="did"/>
<result property="name" column="dname"/>
</association>
</resultMap>
<!--嵌套结果-->
<!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
<select id="findAll" resultMap="ProductMap">
SELECT p.*,d.id did,d.name dname FROM product p
JOIN productdir d on d.id=p.dir_id
</select>
</mapper>
嵌套查询
会产生n+1条sql
需要去找到对应的那条sql并且执行
保证MyBatis能找到这两个xml
ProductdirMapper.xml
<?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="cn.cxm.many2one.mapper.ProductdirMapper">
<select id="findOne" parameterType="long" resultType="cn.cxm.many2one.domain.Productdir">
SELECT* FROM productdir WHERE id=#{id}
</select>
</mapper>
Product.xml
<?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="cn.cxm.many2one.mapper.ProductMapper">
<resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
<id property="id" column="id"/>
<result property="name" column="productName"/>
<result property="salePrice" column="salePrice"/>
<result property="supplier" column="supplier"/>
<result property="brand" column="brand"/>
<result property="cutoff" column="cutoff"/>
<result property="costPrice" column="costPrice"/>
<association property="productdir" javaType="cn.cxm.many2one.domain.Productdir"
column="dir_id" select="cn.cxm.many2one.mapper.ProductdirMapper.findOne"
>
</association>
</resultMap>
<!--嵌套查询-->
<select id="findAll" resultMap="ProductMap">
SELECT * FROM product p
</select>
</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="cn.cxm.many2one.mapper.ProductMapper">
<resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
<!--野方法,直接设置值-->
<result property="productdir.id" column="did" />
<result property="productdir.name" column="dname" />
</resultMap>
<!--野方法-->
<select id="findAll" resultMap="ProductMap">
SELECT p.*,d.id did,d.name dname FROM product p
JOIN productdir d on d.id=p.dir_id
</select>
</mapper>
一对多
Product
private Long id;
private String name;
// private Long dirId;
private Double salePrice;
private String supplier;
private String brand;
private Double cutoff;
private Double costPrice;
Productdir
private Long id;
private String name;
private List<Product> product=new ArrayList<>();
嵌套结果
<?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="cn.cxm.one2many.mapper.ProductdirMapper">
<!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
<resultMap id="ProductdirMap" type="cn.cxm.one2many.domain.Productdir">
<id property="id" column="did"/>
<result property="name" column="dname"/>
<!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
<collection property="product" ofType="cn.cxm.one2many.domain.Product">
<id property="id" column="pid"/>
<result property="name" column="pname"/>
<result property="salePrice" column="psalePrice"/>
<result property="supplier" column="psupplier"/>
<result property="brand" column="pbrand"/>
<result property="cutoff" column="pcutoff"/>
<result property="costPrice" column="pcostPrice"/>
</collection>
</resultMap>
<!--嵌套结果-->
<!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
<select id="findAll" resultMap="ProductdirMap">
SELECT d.id did,d.name dname,p.id pid,p.ProductName pname,p.salePrice psalePrice,
p.supplier psupplier,p.brand pbrand ,p.cutoff pcutoff,p.costPrice pcostPrice FROM productdir d
LEFT JOIN product p on d.id=p.dir_id
</select>
</mapper>
嵌套查询
productMapper
<?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="cn.cxm.one2many.mapper.ProductMapper">
<select id="findBydeptId" parameterType="long" resultType="cn.cxm.one2many.domain.Product">
SELECT * FROM product WHERE dir_id=#{id}
</select>
</mapper>
productdirMapper
<?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="cn.cxm.one2many.mapper.ProductdirMapper">
<!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
<resultMap id="ProductdirMap" type="cn.cxm.one2many.domain.Productdir">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
<collection property="product" ofType="cn.cxm.one2many.domain.Product"
column="id" select="cn.cxm.one2many.mapper.ProductMapper.findBydeptId">
</collection>
</resultMap>
<!--嵌套结果-->
<!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
<select id="findAll" resultMap="ProductdirMap">
SELECT * FROM productdir p
</select>
</mapper>
缓存
自带一级级联
二级缓存需要加上标签 <cache />
二级缓存的对象必需是序列化对象 .. implements Serializable
本文介绍了Mybatis的高级查询技巧,包括如何进行映射Mapper配置,实现动态SQL以进行批量删除和添加。此外,详细讨论了多对一和一对多的关系映射,以及嵌套结果和查询的处理方法。最后,还涉及了Mybatis的缓存机制。

被折叠的 条评论
为什么被折叠?



