MyBatis学习之映射器Mapper(接口映射器+xml映射文件)

Table of Contents

 

01 MyBatis映射器:

1.1 接口映射器+xml映射器

1.2 接口映射器+注解

02 接口映射器+xml映射器  方式

2.1 mybatis配置文件 引入映射器:

2.2 XML映射文件 的几个顶级元素:

2.2.1 select元素 以及Select 元素的属性

2.2.2 insert, update 和 delete元素

2.2.3 sql代码段(可复用)

03 简单demo:

3.1 创建数据库:

3.2 mybatis配置文件:mybatisConfig.xml

3.3 实体类User.java:

3.4 持久层接口IUserDao.java:

3.5 对应的XML映射文件:

3.6 编写测试类DemoTest.java:

3.7 运行结果:

04 小结:


01 MyBatis映射器:

映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持XML映射器,所有的SQL语句都必须在XML文件中配置。而从MyBatis 3开始,开始支持接口映射器,其底层利用的是接口绑定技术。另外,接口映射器允许通过注解定义SQL语句,用以替代XML文件配置SQL。

  • 1.1 接口映射器+xml映射器

先定义接口映射器,然后再定义xml映射器,其中xml映射器的namespace应该对应接口映射器的类名。

  • 1.2 接口映射器+注解

此类形式,将原先xml里面的sql配置信息,变成Java注解的形式写到接口映射器

这里先记录 接口映射器+xml映射文件,后面才写 接口映射器+注解 的笔记

02 接口映射器+xml映射器  方式

2.1 mybatis配置文件 引入映射器:

在MyBatis配置文件中包含了<mappers></mappers>节点,这里就是MyBatis映射器。

  • 接口映射器+xml映射器  方式时,在mybatis配置文件中引入映射器  代码如下 :
<mappers>
 <mapper resource="cn/mybatis/mydemo/mapper/StudentMapper.xml"/>
</mappers

注意:此种⽅法要求mapper接⼝名称和mapper映射⽂件名称相同,且放在同⼀个⽬录中

 

 

2.2 XML映射文件 的几个顶级元素:

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache – 给定命名空间的缓存配置。
  • cache-ref – 其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

2.2.1 select元素 以及Select 元素的属性

select 元素允许你配置很多属性来配置每条语句的作用细节。

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

 

Select 元素的属性
属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。对应接口中的某个方法名
parameterType将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler) 推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap这是引用外部 parameterMap 的已经被废弃的方法。请使用内联参数映射和 parameterType 属性。
resultType从这条语句中返回的期望类型的类的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用。
resultMap外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂映射的情形都能迎刃而解。可以使用 resultMap 或 resultType,但不能同时使用。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)。
fetchSize这是一个给驱动的提示,尝试让驱动程序每次批量返回的结果行数和这个设置值相等。 默认值为未设置(unset)(依赖驱动)。
statementTypeSTATEMENT,PREPARED 或 CALLABLE 中的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetTypeFORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖驱动)。
databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。 这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。
resultSets这个设置仅对多结果集的情况适用。它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的。
  • 简单查询的 select 示例

查询语句是 MyBatis 中最常用的元素之一,简单查询的 select 元素是非常简单的。比如:

<mapper namespace="cn.mybatis.mydemo.mapper.StudentMapper">
    <select id="getStudent" parameterType="long" resultType="student">
        SELECT id,name,address FROM Student WHERE id =#{id}
    </select>
</mapper>
  • namespace是对应接口的全限定名,于是 MyBatis 上下文就可以通过它找到对应的接口。
  • <select> 元素表明这是一条查询语句
  •  id 标识了这条 SQL,id对应的是接口的某个方法
  • resultType="student" 表示返回的是一个 Student 类型的返回值。而 student是配置文件 mybatis-config.xml 配置的别名,指代的是 com.mybatis.domain.Student
  •  parameterType="long" 说明传递给 SQL 的是一个 long 型的参数
  • #{id} 表示传递进去的参数。

注意:这里并没有配置 SQL 执行后和 Student 的对应关系,它是如何映射的呢?其实,这里采用的是一种被称为自动映射的功能,MyBatis在默认情况下提供自动映射,只要SQL返回的列名能和POJO的属性对应起来即可。

 

2.2.2 insert, update 和 delete元素

数据变更语句 insert,update 和 delete 的实现非常接近:

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">
Insert, Update, Delete 元素的属性
属性描述
id命名空间中的唯一标识符,可被用来代表这条语句。
parameterType将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap这是引用外部 parameterMap 的已经被废弃的方法。请使用内联参数映射和 parameterType 属性。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:true(对于 insert、update 和 delete 语句)。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)。
statementTypeSTATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
keyColumn(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。
databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
  • 下面就是 insert,update 和 delete 语句的示例:
<insert id="insertAuthor">
  insert into Author (id,username,password,email,bio)
  values (#{id},#{username},#{password},#{email},#{bio})
</insert>

<update id="updateAuthor">
  update Author set
    username = #{username},
    password = #{password},
    email = #{email},
    bio = #{bio}
  where id = #{id}
</update>

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>

首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就 OK 了。例如,如果上面的 Author 表已经对 id 使用了自动生成的列类型,那么语句可以修改为:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

2.2.3 sql代码段(可复用)

这个元素可以被用来定义可重用的 SQL 代码段,这些 SQL 代码可以被包含在其他语句中。它可以(在加载的时候)被静态地设置参数。 在不同的包含语句中可以设置不同的值到参数占位符上。比如:

<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

这个 SQL 片段可以被包含在其他语句中,例如:

<select id="selectUsers" resultType="map">
  select
    <include refid="userColumns"><property name="alias" value="t1"/></include>,
    <include refid="userColumns"><property name="alias" value="t2"/></include>
  from some_table t1
    cross join some_table t2
</select>

refid="userColumns" 对应sql中的id

 

03 简单demo:

3.1 创建数据库:

3.2 mybatis配置文件:mybatisConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置环境 -->
    <environments default="development">
        <!-- 配置mysql环境 -->
        <environment id="development">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源连接池 -->
            <dataSource type="POOLED">
                <!-- 这⾥⽤得是mysql8的驱动包 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
<!--        引入这个XML映射器文件-->
        <mapper resource="demo/dao/IUserDao.xml"/>
    </mappers>

</configuration>

3.3 实体类User.java:

public class User {
    private int id;
    private String username;
    private String sex;
    private String address;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" +id+
                ",username=" +username+
                ",sex=" +sex+
                "address=" +address+
                "}";
    }
}

3.4 持久层接口IUserDao.java:

public interface IUserDao {
    /**
     * 查找所有用户
     * @return
     */
    public List<User> findAllUser();
}

3.5 对应的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="demo.dao.IUserDao">
    <select id="findAllUser" resultType="demo.domain.User">
     select * from user
     </select>
</mapper>

注意:此种⽅法要求mapper接⼝名称和mapper映射⽂件名称相同,且放在同⼀个⽬录中

还有,这里个人喜欢叫Dao命名,而不是Mapper,看个人爱好

只要,接⼝名称和映射  ⽂件名称相同,且放在同⼀个⽬录中即可

3.6 编写测试类DemoTest.java:

public class DemoTest {
    InputStream inputStream;
    SqlSession session;
    SqlSessionFactory sqlSessionFactory;
    @Before
    public void init() throws IOException {
        //1.读取配置⽂件
        inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
        //2.创建SqlSessionFactory的构建者对象,使⽤构建者创建⼯⼚对象SqlSessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.使⽤SqlSessionFactory⽣产SqlSession对象
        session = sqlSessionFactory.openSession();
    }
    @After
    public void destroy() throws IOException{
        //6.释放资源
        session.close();
        inputStream.close();
    }
    @Test
    public void test() throws IOException {
        //4.使⽤SqlSession创建dao接⼝的代理对象
        IUserDao userDao = session.getMapper(IUserDao.class);
        //5.使⽤代理对象执⾏查询所有⽅法
        List<User> users = userDao.findAllUser();
        for (User user : users){
            System.out.println(user);
        }
    }
}

 @Before、@After、@Test是Junit的注解,@Before是运行前指定执行的方法是public void init(),@After类似

3.7 运行结果:

04 小结:

1.映射器只是一个接口,而不是一个实现类。初学者可能会产生一个很大的疑问:接口不是不能运行吗?的确,接口不能直接运行,但是MyBatis内部运用了动态代理技术,生成接口的实现类,从而完成接口的相关功能。只要明白 MyBatis 会为这个接口生成一个代理对象,代理对象会去处理映射器接口相关的逻辑即可。

然后调用mybatis对象SQLSession的getMapper()获取代理对象,调用接口的方法

2.我们并没有配置 SQL 执行后和 User 的对应关系,它是如何映射的呢?其实,这里采用的是一种被称为自动映射的功能,MyBatis在默认情况下提供自动映射,只要SQL返回的列名能和POJO的属性对应起来即可。

后面会讲到当 实体类属性 和 数据库列名 不一一相同 如何 做映射

 3.接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以。

接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定,在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。

当Sql语句比较简单时候,用注解绑定,当SQL语句比较复杂时候,用xml绑定。

一般情况下,用xml绑定的比较多。

使用MyBatis的mapper接口调用时要注意的事项有:

(1)Mapper接口方法名和mapper.xml中定义的每个sql的id相同;

(2)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;

(3)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;

(4)Mapper.xml文件中的namespace即是mapper接口的类路径。

  • 9
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值