mybatis中用xml文件方式实现接口类

mybatis中用xml文件方式实现接口类

老师,在本章教学视频中,发现在dao层的PersonMapper.java是个接口类,里面提到说它的实现就是对应了mybatis下的PersonMapper.xml(即mybatis的映射配置文件)

我有点疑惑,在mybatis中,一个xml文件里也可以实现接口么?如果是这样的话,那接口的方法是怎么被实现的呢?是xml当中id为接口方法名的那个标签下增删改查实体么?

正在回答

登陆购买课程后可参与讨论,去登陆

6回答

同学你好,首先方法中有多个参数时,就不再使用sqlSession中的方法。需要使用自定义方法。


例如:

PersonMapper类:

http://img1.sycdn.imooc.com//climg/5d3518b6000171ce06130062.jpg

Xml 文件中

http://img1.sycdn.imooc.com//climg/5d3519040001c71e06180093.jpg

测试

http://img1.sycdn.imooc.com//climg/5d35195d0001b35506200176.jpg

多参数传递可以按照如上方式进行。


其次,在之后的课程中,除了涉及到JavaBean对象,集合传参,也是有多个参数传递的详细讲解哦~

建议同学先观看讲解多参数传递的视频,看的时候根据视频敲遍代码,有什么不明白的,欢迎继续提问哦~


如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 哆丶哆 提问者 #1
    理解了,谢谢老师耐心解答
    2019-07-22 12:26:12
提问者 哆丶哆 2019-07-21 19:22:02

就比如说这个例子,下面的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属性是用来配置命名空间,主要进行session级别的缓存管理
命名空间默认情况下,使用我们当前操作的实体类的全路径
-->
<mapper namespace="com.damu.entity.Users">

    <!--<select id="findUsers" resultType="com.damu.entity.Users">-->
    <select id="findUsers" resultMap="forUsers">
        select * from users

        <if test="id != null">
            where id = #{id}
        </if>
    </select>

    <!-- 自定义映射关系集合:主要包含对于一些自定义操作的配置,如不一致的属性和字段 -->
    <resultMap id="forUsers" type="com.damu.entity.Users">
        <!-- 绑定id主键 -->
        <id property="id" column="id"></id>
        <!-- result配置,主要配置普通属性,column表示配置的是数据库字段名称 property配置的是实体类的属性名称 -->
        <result column="username" property="name"></result>

        <collection property="addresses" column="id" ofType="com.damu.entity.Address" select="getAddress"></collection>
    </resultMap>

    <select id="getAddress" resultType="com.damu.entity.Address">
        select * from address where userid = #{id}
    </select>

    

    <sql id="user_fields">
        username, userpass, nickname, age, gender, email, phone, createTime, updateTime, lastLogin, userstatus, remark
    </sql>

    <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
        insert into users( <include refid="user_fields"></include>)
        values(#{name},#{userpass}, #{nickname}, #{age}, #{gender}, #{email}, #{phone}, #{createTime}, #{updateTime}, #{lastLogin}, #{userStatus}, #{remark})
    </insert>

    <update id="updateUser">
        update users
        <set>
            <if test="name != null">username = #{name},</if>
            <if test="userpass != null">userpass = #{userpass},</if>
            <if test="nickname != null">nickname = #{nickname},</if>
            <if test="age != null">age = #{age},</if>
            <if test="gender != null">gender = #{gender},</if>
            <if test="email != null">email = #{email},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="createTime != null">createTime = #{createTime},</if>
            <if test="updateTime != null">updateTime = #{updateTime},</if>
            <if test="lastLogin != null">lastlogin = #{lastLogin},</if>
            <if test="userStatus != null">userStatus = #{userStatus},</if>
            <if test="remark != null">remark = #{remark},</if>
        </set>
          where id = #{id}
    </update>

    <delete id="delUser">
        delete from users where id = #{id}
    </delete>
</mapper>

然后在dao层调用sql语句的时候,是用SqlSession对象来执行语句的对不对?如下:

package com.damu.dao;

import com.damu.entity.Users;
import com.damu.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

/**
 * Created by mouwe on 2017/5/23.
 */
public class UsersDAO {
    private SqlSession sqlSession;
    private List<Users> list;
    private Users user;

    private SqlSession getSession() {
        sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
        return sqlSession;
    }

    /**
     * 查询全部用户
     * @return
     */
    public List<Users> findAll() {
        try {
            list = getSession().selectList("findUsers");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return list;
    }

    /**
     * 查询单个用户根据编号
     * @return
     */
    public Users findById(Integer id) {
        try {
            user = getSession().selectOne("findUsers", new Users(id));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return user;
    }

    /**
     * 增加一个新用户数据到数据库的方法
     * @return
     */
    public Users addUser(Users user) {
        try {

            // 返回值:是insert执行过程中影响的行数
            getSession().insert("addUser", user);

            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return user;
    }


    /**
     * 用于修改用户资料的方法
     * @return
     */
    public Users updateUsers(Users user) {
        try {

            // 返回值:是insert执行过程中影响的行数
            getSession().update("updateUser", user);

            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return user;
    }

    /**
     * 用于修改用户资料的方法
     * @return
     */
    public void delUsers(Integer id) {
        try {

            // 返回值:是insert执行过程中影响的行数
            getSession().delete("delUser", id);

            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
    }

}

其中,这里的 

list = getSession().selectList("findUsers");  

user = getSession().selectOne("findUsers", new Users(id));

getSession().insert("addUser", user);

  getSession().update("updateUser", user);

上述的SqlSession的方法是不是传入了最多两个参数,第一个参数是xml标签对应的id值,表示执行哪条SQL语句,而第二个参数是封装成了一个javabean对象来传参,这个是多参处理的方式之一。就如果我不用封装JavaBean对象或者集合的方式,那么这种方式下要怎么传多个参数?

是这样子么?

list = getSession().selectList("findUsers",参数1,参数2,参数3...........);

就是说SqlSession中的select方法、insert方法、delete方法,可以直接传无穷个参数?

吃吃吃鱼的猫 2019-07-21 18:57:46

同学你好,同学所说的“原始的方式(即命名空间映射的是一个实体类不是接口)”来做为参数传递是什么意思呢?

是将实体类做为参数吗?如果是的话,是可以的哦~

例如:User对象做为参数。

同学可以进行测试~

其次,建议同学根据视频多敲几遍代码,练习几遍,加深对视频中知识点的理解哦~
如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

吃吃吃鱼的猫 2019-07-21 15:34:02

同学你好,

1、多参数传递在后面的课程中有详细讲解~

2、查询不改变数据,所以查询时不用使用事务。有关于事务的课程在之后的课程中有详细讲解,同学不用着急哦~按照视频循序渐进的学习就可以呢~

3、selectOne查询出的就是一条记录,selectList查询出的是记录的集合。

可以说MyBatis是对JDBC的一个封装,优化。这样做比之前返回结果集更方便。

4、PersonMapper.class是获取PersonMapper类的对象,getMapper方法是SqlSession内部封装好的方法,可以直接使用,表示:返回绑定到此sqlsession的映射。

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 哆丶哆 #1
    老师,对于第一问,我是看过视频之后才问的呢。我问的是在使用SqlSession对象来调用selectList、selctOne、update、delete等方法执行SQL语句的时候,这些方法不是最多两个参数么,第一个参数是固定的xml映射的id值,第二个参数是传给SQL的参数,这里如果不使用封装对象和集合的办法,怎么能做到传入多个参数呢? 后面的课程是有提到传多参的方法,但是它是通过映射一个接口来实现的,我想先用原始的方式(即命名空间映射的是一个实体类不是接口)试试
    2019-07-21 16:46:47
提问者 哆丶哆 2019-07-21 14:11:58

那也就是说命名空间就是一个接口类咯?那刚开始视频教学是说命名空间默认情况下,使用我们当前操作的实体类的全路径。在里面编写SQL语句后,调用SqlSession的对应方法执行。

  1. 在命名空间是实体类的情况下,是通过SqlSession对象的selectList、selctOne、update、delete方法来执行xml里面的SQL语句的,其中第一个参数就是xml对应标签的id值,表示调用哪一个SQL语句。第二个则是代表传入的参数,可是这里只能传入一个参数么?我看这些方法要么就是只有一个id值参数,要么就是后面穿了个javabean对象,如果在xml中涉及到多参处理的话,我又不用封装JavaBean或者集合类的方法,要直接传多个参数怎么办?

  2. 视频中提到说mybatis的事务是默认不会自动提交的,可是我看了下查询的操作,也没有调用commit方法,就可以获得查询的结果,但是增删改却要加commit,查询是特例么?

  3. 在以前学习JDBC的时候,查询操作可以用executorQuery方法获取,不管查询某条记录还是一堆记录,得到的都是一个结果集ResultSet对象,可以通过遍历结果集获取每条记录。但是在mybatis我发现,查询一条记录时,SqlSession调用了selectOne方法,查多条记录用的是selectList方法,那这样的话不就得提前知道我查询的是某条记录还是记录的集合?有没一种方法能像JDBC返回结果集那样,返回一个结果集对象,不管是一条记录还是多条记录都封装在这个结果集里面呢?

  4. 之前视频映射的xml文件对应一个实体类,这次对应一个接口类,发现调用SQL语句的方法也有所不同。对应接口的话,直接用接口方法名即可,不用像之前那样传入一个id值的参数。我发现在xml映射一个接口类的时候,调用方法前有个反射的过程,如下例子:


  5.     /**
         * 根据ID删除所对应的Person数据
         */
        public void deletePerson() {
            SqlSession sqlSession = this.getSqlSessionFactory().openSession();
    
            PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
    
            personMapper.deletePerson(2);
    
            sqlSession.commit();
    
    
        }

请问这里的 PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);语句是什么意思?类名.class是获取一个类的class文件对应的Class对象,这里通过一个Class对象返回的是它所反射的一个实体类对象,这个方法是已经SqlSession类内部集成好直接拿来用的么?


吃吃吃鱼的猫 2019-07-21 12:01:08

同学你好,Mybatis内部通过读取xml文件和反射实现dao接口所有方法。

这些,Mybatis内部为我们实现,我们不需要关心其中的细节,只需要按照文档中所要求的进行配置即可。

一般来说,一个xml文件里只对应一个接口,接口中的方法与xml文件中对应标签的id所对应。

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师