分布式机器 element idea facebook ipad swagger 管理后台框架 it教学视频 jquery绑定click事件 jquery获取元素 arraylist删除指定元素 vim跳到文件末尾 安装mysql python注释 python编译环境 python环境安装教程 python抛出异常 java获取当前年 java时间转换 莫愁脚本 flash实例教程 abaqus最新版本 java程序设计基础 服务器系统安装 微信彩色字 vs2003 findall 微信公众号点餐系统 backtrack4 execryptor cad乘号 平原门下客三千 安卓游戏辅助 allowtransparency 红巨星插件 pr脱机文件怎么恢复 origin柱状图 ps原位粘贴 urlpattern cad指北针
当前位置: 首页 > 学习教程  > 编程语言

【MyBatis框架】MyBatis实现复杂CRUD:多表查询、动态sql等

2020/11/24 10:35:43 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

接上篇博客&#xff1a; O、必要的一些准备 Bean类&#xff0c;这里略写 Dao&#xff1a;这里定义了之后要实现的操作数据库的方法 public interface StudentDao2 {//in 查询public List<Student> finda(List list);public List<Student> findb(int[] ids);pub…

接上篇博客:

O、必要的一些准备

Bean类,这里略写

Dao:这里定义了之后要实现的操作数据库的方法

public interface StudentDao2 {
    //in 查询
    public List<Student> finda(List list);
    public List<Student> findb(int[] ids);
    public List<Student> findc(Map map);
    //模糊查询, 根据学生姓名和编号进行查询
    public List<Student> findd(Map map);
    public List<Student> finde(Student student);
    //查询StudentId在1-5之间的数据
    public List<Student> findf(Map map);
}

一、 in 查询:for each

in查询使用for each标签来实现

for each标签中属性说明:

  • item 表示集合中每一个元素进行迭代时的别名,等同于c标签中的var
  • index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置,可以不写
  • open 表示该语句以什么开始
  • separator 表示在每次进行迭代之间以什么符号作为分隔符
  • close 表示以什么结束

注意:在使用for each的时候最关键的也是最容易出错的就是collection属性,collection该属性是必须指定的:

  • collection 表示传入的参数类型:list 时取值list,数组时取值array,map时取值map的key值。

因为在这里传入的参数数量为1,故parameterType的值可以省略

下面分参数为list、array、map形式分别举例:

1.1 参数是list

对应dao中

public List<Student> finda(List list);

mapper中

<select id="finda" resultType="com.maven.bean.Student">
    select * from student where studentId in
    <foreach collection="list" item="sid" open="(" close=")" separator=",">
        #{sid}
    </foreach>
</select>

上面的sql语句等价于:

select * from student where studentId in (#{sid});

1.2 参数是数组array

<select id="findb" resultType="com.maven.bean.Student">
    select * from student where studentId in
    <foreach collection="array" item="sid" open="(" close=")" separator=",">
        #{sid}
    </foreach>
</select>

1.3 参数是Map

<select id="findc" resultType="com.maven.bean.Student">
    select * from student where studentId in
    <foreach collection="ids" item="sid" open="(" close=")" separator=",">
        #{sid}
    </foreach>
</select>

二、动态sql

前面几篇博客我们通过实例讲解了用mybatis对一张表进行的CRUD操作,但是我们发现写的SQL 语句都比较简单,如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。

那么怎么去解决这个问题呢?可以使用MyBatis中的动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。

2.1 模糊查询

格式:

<if test="属性名!=属性值">
    and ename like '${属性名}'
</if>
  • 注意:test属性中读取属性值时直接写属性名。
  • 模糊查询读取属性时使el 表达式,${属性名}。除以上位置外,都使用#{属性名}
  • 多个条件时使用and,or 拼接
  • 如果传递过来的是map类型,则test属性中写的是key

dao:

//模糊查询, 根据学生姓名和编号进行查询
public List<Student> findd(Map map);
public List<Student> finde(Student student);

mapper:

<!--参数为Map形式, 传入的都是key值-->
<select id="findd" resultType="com.maven.bean.Student">
    select * from student where 1=1
    <if test="sname!=null and sname!=''">
    <!--这边用"%"#{sname}"%"也可以-->
        and stuName like '%${sname}%'
    </if>
    <if test="sno!=null and sno!=''">
        and studentNo=#{sno}
    </if>
</select>
<!--参数为Bean形式, 传入的都是属性-->
<select id="finde" resultType="com.maven.bean.Student">
    select * from student where 1=1
    <if test="stuName!=null and stuName!=''">
        <!--这边用"%"#{sname}"%"也可以-->
        and stuName like '%${stuName}%'
    </if>
    <if test="studentNo!=null and studentNo!=''">
        and studentNo=#{studentNo}
    </if>
</select>
  • 如果传递的参数是多个时?------使用Map 集合
  • #{} 表示占位符,安全
  • 表 示 拼 接 s q l 语 句 , {} 表示拼接sql语句, sql{} 会引起SQL注入,一般情况下不推荐使用。

示例:

<if test="ename!=null and ename!=''">
    and ename like '%${属性名}%'
</if>
或者:
	and sname like "%"#{username}"%"
或者:
	sname like concat(concat('%',#{username}),'%')

2.2 区间查询

dao:

//查询StudentId在1-5之间的数据
public List<Student> findf(Map map);

between 开始值 and 结束值

列名 >=开始时间 and 列名<=结束时间

<select id="findf" resultType="student">
    <!-- select * from student where studentId between #{begin} and #{end} -->
    select * from student where studentId>=#{begin} and studentId <![CDATA[<=]]> #{end}
</select>

三、使用resultMap处理表关系

3.1 处理单表关系

通过给列起别名,让别名=属性名,也可以实现数据对应

resultType=“指定返回值的类型” //当列名和属性名一致时使用

resultMap=“key 值” //1.当列名和属性名不一致 2.做多表查询时 使用

<resultMap id="aaa" type="bean.Dept">
    <!-- 可以手动指定列名和属性名的关系 ,非主键列使用result 标签,主键
列使用id 标签-->
    <id property="dept_no" column="deptno"></id>
    <result property="d_name" column="dname"/>
    <result property="d_loc" column="loc"/>
</resultMap>

例如:

<resultMap id="rs6" type="com.maven.bean.Husband">
    <id property="husId" column="husid"></id>
    <result property="husName" column="husname"></result>
</resultMap>

3.2 处理多表关系

两表联查共分为:一对多、多对一、多对多、一对多,四种情况

  • 如果是单表查询,select 中使用resultType 设置返回的类型即可
  • 但是如果是多表联查,那么select 查询的结果需要单独使用resultMap 标签来进行结果的映射
  • 存的是集合的话使用Collection 子标签
  • 存的是一方的话使用association 子标签
  • resultType 和resultMap 属性只能出现一个

总之还是记住一句话,多方存一方的对象,一方存多方的集合

下面就这四种情况作一一举例:

3.2.1 一对多,多对一

dao:

public interface GradeDao {
    //根据年级id查询年级和学生信息: 操作年级信息,在其中包含了学生信息(1=>多)
    public Grade findByGid(int id);
    //查询学生信息以及对应的年级信息: 操作学生信息,在其中包含了年级信息(多=>1)
    public List<Student> findAllStudent();
}

bean:

//一方
public class Grade {
    private int gid;
    private String gname;
    //一方有多方的集合
    private List<Student> studentList;
    getset(){};
}
//多方
public class Student implements Serializable {
    private int studentId;
    private String studentNo;
    private String stuName;
    //多方有一方的对象
    private Grade grade;
    //private int stuAge;
    private int age;
    getset(){};
}

mapper:

<!--namespace="接口的完整路径"-->
<mapper namespace="com.maven.dao.GradeDao">
    <resultMap id="rs2" type="com.maven.bean.Grade">
        <!--先描述自身的信息,然后描述关联表的信息-->
        <!--id描述主键列,非主键列使用result描述-->
        <id column="gid" property="gid"></id>
        <result column="gname" property="gname"></result>
        <collection property="studentList" ofType="com.maven.bean.Student">
            <id column="studentId" property="studentId"></id>
            <result column="stuName" property="stuName"></result>
            <result column="studentNo" property="studentNo"></result>
            <result column="stuAge" property="age"></result>
        </collection>
    </resultMap>
    <resultMap id="rs3" type="com.maven.bean.Student">
        <!--先描述自身的信息,然后描述关联表的信息-->
        <!--id描述主键列,非主键列使用result描述-->
        <id column="studentId" property="studentId"></id>
        <result column="stuName" property="stuName"></result>
        <result column="studentNo" property="studentNo"></result>
        <result column="stuAge" property="age"></result>
        <association property="grade" javaType="com.maven.bean.Grade">
            <id column="gid" property="gid"></id>
            <result column="gname" property="gname"></result>
        </association>
    </resultMap>
    <select id="findByGid" resultMap="rs2">
        select * from grade g,student s
        where s.gradeid=g.gid and g.gid=#{id};
    </select>

    <select id="findAllStudent" resultMap="rs3">
        select * from grade g,student s
        where s.gradeid=g.gid
    </select>
</mapper>

3.2.2 多对多

dao:

public interface RoleDao {
    //1.查询某个角色以及对应的菜单
    public Role findByRoleId(int roleId);
    //2.查询某个菜单以及对应的角色
    public Menu findByMenuId(int menuId);
}

bean:

//多方
public class Menu {
    private int menuId;
    private String menuName;
    private String menuPath;
    private List<Role> roleList;
    getset(){};
}
//多方
public class Role {
    private int roleId;
    private String roleName;
    private List<Menu> menuList;
    getset(){};
}

mapper:

<!--namespace="接口的完整路径"-->
<mapper namespace="com.maven.dao.RoleDao">
    <resultMap id="rs4" type="com.maven.bean.Role">
        <id property="roleId" column="roleid"></id>
        <result property="roleName" column="rolename"></result>
        <collection property="menuList" ofType="com.maven.bean.Menu">
            <id property="menuId" column="menuid"></id>
            <result property="menuName" column="menuname"></result>
            <result property="menuPath" column="menupath"></result>
        </collection>
    </resultMap>
    <resultMap id="rs5" type="com.maven.bean.Menu">
        <id property="menuId" column="menuid"></id>
        <result property="menuName" column="menuname"></result>
        <result property="menuPath" column="menupath"></result>
        <collection property="roleList" ofType="com.maven.bean.Role">
            <id property="roleId" column="roleid"></id>
            <result property="roleName" column="rolename"></result>
        </collection>
    </resultMap>
    <select id="findByRoleId" resultMap="rs4">
        select * from role r,menu m,middle mid
        where r.roleid=mid.roleid and m.menuid=mid.menuid and r.roleid=#{roleId};
    </select>
    <select id="findByMenuId" resultMap="rs5">
        select * from role r,menu m,middle mid
        where r.roleid=mid.roleid and m.menuid=mid.menuid and m.menuid=#{menuId};
    </select>
</mapper>

3.2.3 一对一

dao:

public interface WifeDao {
    //1.根据丈夫查询妻子(首先查的是丈夫, 丈夫里带了妻子的属性)
    public Husband findByHusId(int id);
    //2.根据妻子查询丈夫(首先查的是妻子, 丈夫里带了丈夫的属性)
    public Wife findByWifeId(int id);
}

bean:

//一方
public class Husband {
    private int husId;
    private String husName;
    private Wife wife;
    getset(){};
}
//一方
public class Wife {
    private int wifeId;
    private String wifeName;
    private Husband husband;
    getset(){};
}

注意:

  • ofType:指定多方list集合内的对象

  • javaType:指定一方中的对象

  • 外键列不需要添加对应属性


在下篇博客中介绍下如何在MyBatis中实现分页查询


本文链接: http://www.dtmao.cc/news_show_400280.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?