Mybatis框架基础

目录

一、单元测试

二、增删改查

1.向数据库增添数据

2.删除数据库数据

3.修改数据库数据

4.查询返回简单基本类型

5.返回多个数据

三、关联查询

1.多表查询

(1)准备工作

(2)多表查询

        标签

        标签

2.嵌套查询

四、动态sql

1.if元素

2.where元素

3.trim元素

4.choose元素

5.set元素

6.foreach 元素


        在数据库创建admin管理员表为例

一、单元测试

        程序员一般会使用的测试方法,是以方法为单位进行测试,这里需要使用junit组件实现。

在pom.xml文件中加入以下代码。

<!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>provided</scope>
        </dependency>

这样我们就可以在方法外加上@Test注解标签直接对该方法实现运行测试,如图

二、增删改查

1.向数据库增添数据

@Test
    public void insert(){
        Admin admin = new Admin();//数据封装到对象中
        admin.setAccount("aaa");
        admin.setPassword("132");
        admin.setGender("男");
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
                 adminDao.insertAdmin(admin);//拿主键
                 System.out.println(admin.getId());
                 sqlSession.commit();//提交数据库事务,程序无异常才提交事务,执行sql。新增修改删除完成后都需手动提交事务
//void insertAdmin(Admin admin);接口中的方法
                 sqlSession.close();
        /*数据库事物:是数据库的一种管理机制,对一次连接数据库过程进行管理
        例如:
            sql1
            其它代码(有异常)
            sql2
            提交事务(一次执行完所有sql,但是因为在其它代码部分有异常,会终止提交事务,因此sql都不会执行)*/
    }

        映射文件相应标签 

    <!--useGeneratedKeys="返回自增主键"
    keyProperty="接收主键属性"
    keyColumn="主键列"
    -->
    <insert id="insertAdmin" parameterType="Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        insert into admin(account,password,gender)values (#{account},#{password},#{gender})
    </insert>

2.删除数据库数据

        删除id为4的管理员信息

@Test
    public void delete(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        adminDao.deleteAdmin(4);
        sqlSession.commit();
        sqlSession.close();
    }//void deleteAdmin(int id);接口中的方法

        映射文件相应标签 

<delete id="deleteAdmin" parameterType="int">delete from admin where id = #{id}</delete>

3.修改数据库数据

        修改id为3的管理员信息

@Test
    public void update(){
        Admin admin = new Admin();
        admin.setId(3);
        admin.setAccount("ccc");
        admin.setPassword("123");
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        adminDao.updateAdmin(admin);
        sqlSession.commit();
        sqlSession.close();
    }//void updateAdmin(Admin admin);接口中的方法

       映射文件相应标签 

<update id="updateAdmin" parameterType="Admin">update admin set account = #{account},password=#{password} where id = #{id}</update>

4.查询返回简单基本类型

        单表查询,返回的结果mybatis自动将结果映射到java对象中,但必须要表中列名与类中属性名一致!

注:MySQL中对于两个单词采用A_B链接,但是java使用驼峰表示findAdmin,因此这里我们可以在mybatis.xml配置文件中<settings>标签中加入如下代码即可相互转换,还不影响单表查询因为属性名与列名不一致引起的查询失效。

<setting name="mapUnderscoreToCamelCase" value="true"/> 

@Test
    public void find1(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        int count = adminDao.findAdminCount();
        int id = adminDao.findAdminId("account");
        sqlSession.commit();
        sqlSession.close();
    }//int findAdminCount();接口中的方法

       映射文件相应标签 

<!--单表查询,返回的结果mybatis自动将结果映射到java对象中,但必须要表中列名与类中属性名一致-->
    <!--java.lang.Integer,全类名,这里我们用别名integer代替-->
    <select id="findAdminCount" resultType="integer">
        select count(*) from admin
    </select>

5.返回多个数据

@Test
    public void find2(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        List<Admin> admins = adminDao.findAdmins("password");
        sqlSession.commit();
        sqlSession.close();
    }//List<Admin> findAdmins(@Param("orderColumn") String orderColumn);接口方法

        映射文件相应标签 

    <select id="findAdmins" resultType="Admin" parameterType="string">
        select ${orderColumn} from admin order by ${orderColumn} desc
    </select>

三、关联查询

1.多表查询

(1)准备工作

        我们在数据库中再创建两张表student和major

在IDEA分别写出相应的类、接口、映射文件,记得在mybatis.xml配置文件中注册映射文件,如果忘记了具体操作请移步至我的上一篇博客:java后端框架——Mybatis框架搭建

        这里有一点值得我们注意的是,以往我们向通过student学生类查询major专业信息,需要在student类中重新定义专业中的属性,如:mid、mname会发生冗余。但是mybatis在封装时想到,我们只需在student类中定义一个major属性即可。将专业信息封装到学生类中,因为mid、mname本质上在major中已经定义过。这样就在学生中关联了专业。

(2)多表查询
        <association>标签

        因此多表查询,为了使major类的信息存储到student类中我们定义的major属性中去,就需要借助<resultMap>标签。整体结构如下:

//定义 resutlMap
<resultMap id="adminResultMap" type="Admin">
    <id column="id" property="id"/>
    <result property="account" column="account" />
    <result property="password" column="password" />
</resultMap>
注: (1). resutlMap 的 id 属性是 resutlMap 的唯一标识,本例中定义为 “adminResultMap”
        (2). resutlMap 的 type 属性是映射的 POJO 类型(即该类的类型)
        (3). id 标签映射主键,result 标签映射非主键
        (4). property 设置对象属性名称,column 映射查询结果的列名称(这里因为我在IDEA中创建类的属性时名字与数据库列名保持一致故而前后相同,大家根据自己创建类的属性名而定
//使用 resultMap
<select id="findAdminInfoResultMap" resultMap="adminResultMap">
    SELECT id ,account,password FROM admin
</select>
注: (1). 本例的输出映射使用的是 resultMap,而非 resultType
        (2). resultMap 引用了 adminResultMap(这与上面<resultMap>中的id保持一致

        接下来我通过查询学生及其相关专业为例,演示如何映射关联数据。接口中的方法和测试程序我就不再过多赘述,参考上文即可,这里只演示映射文件内容。

    <!--对关联查询到的学生信息进行自定义映射封装-->
    <resultMap id="studentMap" type="Student">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
<!--映射关联数据专业名称 先创建一个Major对象,将专业名称封装到Major对象中,再将major对象封装到Student对象中-->
        <association property="major" javaType="Major">
            <result column="mname" property="name"></result>
        </association>
    </resultMap>
    <select id="findStudentById" resultMap="studentMap">
        select
        s.id,
        s.num,
        s.name,
        s.gender,
        m.name mname
        from student s inner join major m on s.majorid = m.id where s.id = #{id}
    </select>

注: <association>标签映射关联对象数据。该标签头中俩标签内容:

        <property>标签中是要映射关联的类的对象

        <javaType>标签放关联对象的类型

        * 如果多个查询的属性一致,只是查询结果个数不同,如去掉where条件语句,我们可以让两个select查询共同映射同一个Map,即resultMap映射地址一致。

        <connection>标签

        当我们想通过专业查询该专业有多少学生时,可以将多个学生封装到一个集合中,这时就要用到<connection>标签,将查询关联到的多条结果封装到集合中去。

    <resultMap id="majorMap" type="Major">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="students" javaType="list" ofType="Student">
            <result column="num" property="num"></result>
            <result column="sname" property="name"></result>
        </collection>
    </resultMap>
    <select id="findMajorById" resultMap="majorMap" parameterType="int">
        select
        m.id,
        m.name,
        s.num,
        s.name sname
        from major m inner join student s on s.majorid = m.id where m.id = #{id}
    </select>

        其中,collection 和 association 都需要配置 select 和 column 属性,两者配置方法

相同,参考上文。对应关系如下:

        测试代码 :

@Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        MajorDao majorDao = sqlSession.getMapper(MajorDao.class);
        Major major = majorDao.findMajorById(1);
        System.out.println(major.getName());
        for (Student student:major.getStudents()){
            System.out.println(student.getName()+":"+student.getNum());
        }
        sqlSession.close();
    }//Major findMajorById(int id);接口中方法

2.嵌套查询

        场景一:将原本的关联查询分成两步或多步,形成嵌套查询,这样虽然简化了sql语句,但是要进行两次或多次sql查询执行,效率劣势。

        这里同样不赘述接口方法和测试部分,若无法独立编写,请参考文章开头部分。

<!--嵌套查询,先查主表student学生表,再查关联的major专业表-->
<resultMap id="studentMap1" type="Student">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
<!--封装关联表数据-->
        <association property="major" javaType="Major" select="findMajorById" column="majorid">
        </association>
    </resultMap>
    <select id="findStudentById1" resultMap="studentMap1">
        select
        *
        from student s where s.id = #{id}
    </select>
<!--嵌套查询学生关联的专业-->
    <select id="findMajorById" resultType="Major">
        select name from major where id = #{majorid}
    </select>

<association>新属性解释:

        (1). select:指定关联查询对象的 Mapper Statement ID 为 findDeptByID(即等于子查询中的id
        (2). column="majorid":关联查询时将 majorid 列的值传入 findDeptByID,并将 findDeptByID 查询的结果映射到 Emp 的 dept 属性中(即student表的majorid通过此处传给major子表中的id,从而查出专业名称
        对应关系如下图:

        场景二:当我们通过专业表查询相关专业学生时,因为一对多关系,会导致例如:专业只有四个,但学生有五个而使查询结果个数不一致。在实际开发中,如果要对专业查询表进行分页处理,就会因此导致无法分页。

    <!--分页处理,两次查询-->
    <resultMap id="majorMap1" type="Major">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="students" javaType="list" ofType="Student" select="findStudents" column="id">
        </collection>
    </resultMap>
 <!--分两次查询,程序会先执行专业表查询,然后才会通过专业id查出学生,
这样就会固定查出四条数据的结果,分页操作会根据major表的结果执行,而不受关联表查询结果影响-->
    <select id="findMajor1" resultMap="majorMap1">
        select id,name from major
    </select>
    <select id="findStudents" resultType="Student">
        select num,name from student where majorid = #{id}
    </select>

        测试和接口部分代码如下: 

@Test
    public void test3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        MajorDao majorDao = sqlSession.getMapper(MajorDao.class);
        List<Major> major = majorDao.findMajor1();
        sqlSession.close();
    }//List<Major> findMajor1();接口中方法

四、动态sql

        MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用JDBC 或其他相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。

以教师表为例

 

1.if元素

if 标签可以对传入的条件进行判断
<select id="teachers" resultType="com.mybatispro.model.Teacher">
        select * from teacher
                <if test="num!=null">
                    num = #{num}
                </if>
                <if test="name!=null">
                    and name = #{name}
                </if>
</select>

2.where元素

对于查询条件个数不确定的情况,可使用<where>元素。
<where>元素会进行判断,如果它包含的标签中有返回值的话,它就插入一个‘where’。
此外,如果标签返回的内容是以 AND 或 OR 开头,它会剔除掉 AND 或 OR。

 用法就是给上面仨<if>标签外套一个<where>标签即可

3.trim元素

where 标签其实用 trim 也可以表示。当 where 后紧随 AND 或则 OR 的 时候,就去除 AND 或者 OR。prefix:前缀,prefixOverrides:覆盖首部指定内容。
<select id="teachers" resultType="com.mybatispro.model.Teacher">
        select * from teacher
            <trim prefix="where" prefixOverrides="and|or">
                <if test="num!=null">
                    num = #{num}
                </if><!--如果num为空,会消除name前的and保证sql语句正确-->
                <if test="name!=null">
                    and name = #{name}
                </if>
            </trim>
</select>

4.choose元素

配合<when><otherwise>标签使用。when otherwise 相当于if else,可以没有otherwise不能没有when

    <select id="teachers" resultType="com.mybatispro.model.Teacher">
        select * from teacher
        <trim prefix="where" prefixOverrides="and|or">
            <choose><!--如果名字不为空,查该老师信息,否则查王老师信息-->
            <when test="name!=null">
                and name = #{name}
            </when>
            <otherwise>
                and name = '王老师'
            </otherwise>
            </choose>
        </trim>
    </select>

5.set元素

Set 元素可以把最后一个逗号去掉,用于更改操作,保证sql语句正确性
<update id="updateTeacher" parameterType="Teacher">
        update teacher
        <set>
            <if test="num!=null">
                num = #{num},
            </if>
            <if test="name!=null">
                name = #{name},
            </if>
        </set>
        where id = #{id}
    </update>

6.foreach 元素

相当于一个增强for循环。

collection 属性根据传入的参数选择list/array

item 表示集合中每一个元素进行迭代时的别名

open 表示该语句以什么开始
separator 表示在每次进行迭代之间以什么符号作为分隔符
close 表示以什么结束
@Test
    public void test3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);
        teacherDao.deleteTeacher(new  Integer[]{1,2,3});
        sqlSession.commit();
        sqlSession.close();
    }//void deleteTeacher(Integer[] array);接口中方法
<delete id="deleteTeacher" ><!--删除id在(1,2,3)中的老师-->
        delete from teacher where id in 
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete><!--完整sql为:delete from teacher where id in(1,2,3) -->

 以上是关于mybatis的基本知识,希望能给各位带来收获!如有不正,恳请及时指出。

  • 25
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值