MyBatis(二)MyBatis标签

MyBatis 目录

MyBatis select标签

在 MyBatis 中,select 标签是最常用也是功能最强大的 SQL 语言,用于执行查询操作。

select 示例语句如下。

 <select id="selectBlog" resultType="org.mybatis.example.Blog">
        select * from Blog where id = #{id}
    </select>

以上是一个 id 为 selectBlog的映射语句,参数类型为 int,返回结果类型为 Blog。

​ 执行 SQL 语句时可以定义参数,参数可以是一个简单的参数类型,例如 int、float、String;也可以是一个复杂的参数类型,例如 JavaBean、Map 等。MyBatis 提供了强大的映射规则,执行 SQL 后,MyBatis 会将结果集自动映射到 JavaBean 中。

为了使数据库的查询结果和返回值类型中的属性能够自动匹配,通常会对 MySQL 数据库和 JavaBean 采用同一套命名规则,即 Java 命名驼峰规则,这样就不需要再做映射了(数据库表字段名和属性名不一致时需要手动映射)。

参数的传递使用#{参数名},相当于告诉 MyBatis 生成PreparedStatement参数。对于 JDBC,该参数会被标识为“?”。以上 SQL 语句可以使用 JDBC 实现,实现代码如下。

String sql = "select * from Blog where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,userName);

select标签常用属性

下面介绍 select 标签中常用的属性。

属性名称 描 述 备注
id 它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用 如果命名空间+id不唯一,那么 MyBatis 抛出异常
parameterType 表示传入 SQL 语句传入参数类型的全限定名或别名。它是一个可选属性,MyBatis 能推断出具体传入语句的参数 支持基本数据类型和 JavaBean、Map 等复杂数据类型
resultType SQL 语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型,返回时可以使用 resultType 或 resultMap 之一 -
resultMap 它是映射集的引用,与 元素一起使用,返回时可以使用 resultType 或 resultMap 之一 是 MyBatis 最复杂的元素,可以配置映射规则、级联、typeHandler 等
flushCache 用于设置在调用 SQL 语句后是否要求 MyBatis 清空之前查询的本地缓存和二级缓存 默认值为 false,如果设置为 true,则任何时候只要 SQL 语句被调用都将清空本地缓存和二级缓存
useCache 启动二级缓存的开关,默认值为 true,表示将査询结果存入二级缓存中 -
timeout 用于设置超时参数,单位是秒(s),超时将抛出异常 -
fetchSize 获取记录的总条数设定 默认值是数据库厂商提供的 JDBC 驱动所设置的条数
statementType 告诉 MyBatis 使用哪个 JDBC 的 Statement 工作,取值为 STATEMENT(Statement)、 PREPARED(PreparedStatement)、CALLABLE(CallableStatement) -
resultSetType 这是针对 JDBC 的 ResultSet 接口而言,其值可设置为 FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLLJNSENSITIVE(双向滚动,及时更新) -

传递多个参数

现在需要根据 id 和 name 来模糊查询网站信息,显然这涉及到了两个参数。给映射器传递多个参数分为以下三种方法。

  1. 使用Map传递参数
  2. 使用注解传递参数
  3. 使用JavaBean传递参数

下面分别讲解这 3 种方法的具体实现。

1. 使用Map传递参数

使用 MyBatis 提供的 Map 接口作为参数实现,如下所示。

<select id="selectBlogByMap" resultType="org.mybatis.example.Blog" parameterType="map" >
        select * from Blog where id = #{id} and blog_title=#{blogTitle}
    </select>

在 BlogMapper 接口中,方法如下。

public List<Website> selectBlogByMap(Map<String, Object> params);

测试代码如下。

Map<String,Object> paramsMap = new HashMap<String,Object>();
paramsMap.put("id","1");
paramsMap.put("blogTitle","123");
blogMapper.selectByMap(paramsMap);

使用 Map 传递参数虽然简单易用,但是由于这样设置参数需要键值对应,业务关联性不强,开发人员需要深入到程序中看代码,造成可读性下降。

示例代码

BlogMapper

package org.mybatis.example;

import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.Map;

public interface BlogMapper {
    Blog selectBlog(int id);

    Blog selectBlogByMap(Map<String, Object> params);
}

MainApplication

package org.mybatis.example;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class MainApplication {
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            try (SqlSession session = sqlSessionFactory.openSession()) {
                BlogMapper mapper = session.getMapper(BlogMapper.class);
                Map<String,Object> paramsMap = new HashMap<>();
                paramsMap.put("id",1);
                paramsMap.put("blogTitle","博客名称");
                // 你的应用逻辑代码
                Blog blog = mapper.selectBlogByMap(paramsMap);
                System.out.println(blog.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

mybatis-config.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">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/jdbc_test?characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/BlogMapper.xml"/>
    </mappers>
</configuration>

2. 使用注解传递参数

使用 MyBatis 的注解 @Param() 传递参数,如下所示。

BlogMapper.xml

<select id="selectBlogByIdAndName" resultType="org.mybatis.example.Blog" >
        select * from Blog where id = #{id} and blog_title=#{blogTitle}
    </select>

BlogMapper接口

Blog selectBlogByIdAndName(@Param("id")int id,@Param("blogTitle") String blogTitle);

MainApplication

BlogMapper mapper = session.getMapper(BlogMapper.class);
// 你的应用逻辑代码
Blog blog = mapper.selectBlogByIdAndName(1,"博客名称");
System.out.println(blog.toString());

当我们把参数传递给后台时,MyBatis 通过 @Param 提供的名称就会知道 #{name} 代表 name 参数,提高了参数可读性。但是如果这条 SQL 拥有 10 个参数的查询,就会造成可读性下降,增强了代码复杂性。

3. 使用JavaBean传递参数

在参数过多的情况下,MyBatis 允许组织一个 JavaBean,通过简单的 setter 和 getter 方法设置参数,提高可读性。如下所示。

BlogMapper.xml

<select id="selectBlogByBean" resultType="org.mybatis.example.Blog" >
        select * from Blog where id = #{id} and blog_title=#{blogTitle}
    </select>

BlogMapper接口

Blog selectBlogByBean(Blog blog);

MainApplication

BlogMapper mapper = session.getMapper(BlogMapper.class);
                Blog  blogParam = new Blog();
                blogParam.setId(1);
                blogParam.setBlogTitle("博客名称");
                // 你的应用逻辑代码
                Blog blog = mapper.selectBlogByBean(blogParam);
                System.out.println(blog.toString());

区别

以上 3 种方式的区别如下。

  • 使用 Map 传递参数会导致业务可读性的丧失,继而导致后续扩展和维护的困难,所以在实际应用中我们应该果断废弃该方式。
  • 使用 @Param 注解传递参数会受到参数个数的影响。当 n≤5 时,它是最佳的传参方式,因为它更加直观;当 n>5 时,多个参数将给调用带来困难。
  • 当参数个数大于 5 个时,建议使用 JavaBean 方式。

MyBatis insert标签

MyBatis insert 标签用来定义插入语句,执行插入操作。当 MyBatis 执行完一条插入语句后,就会返回其影响数据库的行数。

用法

  1. 修改 BlogMapper.xml,增加插入语句,代码如下。

     <insert id="insertBlog">
            insert into blog(`blog_title`,`desc`) values (#{blogTitle},#{desc});
        </insert>
    
  2. 在 WebsiteMapper 接口中定义一个 add() 方法,代码如下。

    int insertBlog(Blog blog);
    
  3. 测试代码如下。

     BlogMapper mapper = session.getMapper(BlogMapper.class);
                    Blog blogParam = new Blog();
                    blogParam.setBlogTitle("博客名称2");
                    blogParam.setDesc("博客描述2");
                    // 你的应用逻辑代码
                   int i =  mapper.insertBlog(blogParam);
                    System.out.println("共插入了 " + i + " 条记录");
    
  4. 输出

    共插入了 1 条记录
    

insert 标签常用属性

insert 标签中常用的属性如下表。

属性名称 描述 备注
id 它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用 如果命名空间+ id 不唯一,那么 MyBatis 抛出异常
parameterType 传入 SQL 语句的参数类型的全限定名或别名,它是一个可选属性。 支持基本数据类型和 JavaBean、Map 等复杂数据类型
keyProperty 该属性的作用是将插入操作的返回值赋给 PO 类的某个属性,通常为主键对应的属性。如果是联合主键,可以将多个值用逗号隔开。 -
useGeneratedKe 该属性用来设置,是否使用 JDBC 提供的 getGenereatedKeys() 方法,获取数据库内部产生的主键并赋值到 keyProperty 属性设置的请求对象的属性中,例如 MySQL、SQL Server 等自动递增的字段,其默认值为 false。 该属性值设置为 true 后,会将数据库生成的主键回填到请求对象中,以供其他业务使用。
flushCache 该属性用于设置执行该操作后,是否会清空二级缓存和本地缓存,默认值为 true。 -
timeout 该属性用于设置执行该操作的最大时限,如果超时,就抛异常。 -
databaseId 取值范围 oracle、mysql 等,表示数据库厂家;元素内部可通过 来为特定数据库指定不同的 sql 语句。 MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。
keyColumn 该属性用于设置第几列是主键,当主键列不是表中的第 1 列时,就需要设置该属性。如果是联合主键,可以将多个值用逗号隔开。 -

注意:insert 标签中没有 resultType 属性,只有查询操作才需要对返回结果类型进行相应的指定。

主键(自动递增)回填

我们知道,MySQL、SQL Server 等数据库表可以采用自动递增的字段作为其主键,当向这样的数据库表插入数据时,即使不指定自增主键的值,数据库也会根据自增规则自动生成主键并插入到表中。

一些特殊情况下,我们可能需要将这个刚刚生成的主键回填到请求对象(原本不包含主键信息的请求对象)中,供其他业务使用。此时,我们就可以通过在 insert 标签中添加 keyPropertyuseGeneratedKeys 属性,来实现该功能。

下面我们通过一个示例,来演示主键(自动递增)回填功能。

  1. BlogMapper.xml 中 id 为 insertBloginsert 标签添加 keyPropertyuseGeneratedKeys 属性,具体代码如下:

     <insert id="insertBlog" parameterType="org.mybatis.example.Blog" keyProperty="id" useGeneratedKeys="true">
            insert into blog(`blog_title`,`desc`) values (#{blogTitle},#{desc});
        </insert>
    
  2. MainApplication

    BlogMapper mapper = session.getMapper(BlogMapper.class);
    Blog blogParam = new Blog();
    blogParam.setBlogTitle("博客名称2");
    blogParam.setDesc("博客描述2");
    // 你的应用逻辑代码
    int i =  mapper.insertBlog(blogParam);
    System.out.println("共插入了 " + i + " 条记录");
    System.out.println("插入的id为"+blogParam.getId());
    
  3. 输出

    共插入了 1 条记录
    插入的id为5
    

自定义主键

如果在实际项目中,若数据库不支持主键自动递增(例如 Oracle),或者取消了主键自动递增的规则,我们可以使用 MyBatis 的 <selectKey> 标签自定义生成主键,具体配置代码如下。

<insert id="insertBlog" parameterType="org.mybatis.example.Blog">
        <selectKey keyProperty="id" resultType="Integer" order="BEFORE">
            select if(max(id) is null,1,max(id)+1) as newId from blog
        </selectKey>
        insert into blog(id,`blog_title`,`desc`) values (#{id},#{blogTitle},#{desc});
    </insert>

<selectKey> 标签中属性说明如下:

  • keyProperty:用于指定主键值对应的 PO 类的属性。
  • order:该属性取值可以为 BEFORE 或 AFTER。BEFORE 表示先执行 <selectKey> 标签内的语句,再执行插入语句;AFTER 表示先执行插入语句再执行 <selectKey> 标签内的语句。

MyBatis update标签

MyBatis update 标签用于定义更新语句,执行更新操作。当 MyBatis 执行完一条更新语句后,会返回一个整数,表示受影响的数据库记录的行数。

下面我们通过一个示例演示 update 标签的用法。

BlogMapper.xml

<update id="updateBlog" parameterType="org.mybatis.example.Blog">
        update blog set blog_title=#{blogTitle} where id=#{id};
    </update>

BlogMapper

int updateBlog(Blog blog);

MainApplication

 BlogMapper mapper = session.getMapper(BlogMapper.class);
 Blog blogParam = new Blog();
 blogParam.setId(1);
 blogParam.setBlogTitle("博客名称2");
 // 你的应用逻辑代码
int i =  mapper.updateBlog(blogParam);
 System.out.println("共修改了 " + i + " 条记录");

update 标签常用属性

update 标签常用属性如下表。

属性名称 描述 备注
id 它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用 如果命名空间+ id 不唯一,那么 MyBatis 抛出异常
parameterType 传入 SQL 语句的参数类型的全限定名或别名,它是一个可选属性。 支持基本数据类型和 JavaBean、Map 等复杂数据类型
flushCache 该属性用于设置执行该操作后,是否会清空二级缓存和本地缓存,默认值为 true。 -
timeout 该属性用于设置 SQL 执行的超时时间,如果超时,就抛异常。 -
statementType 执行 SQL 时使用的 statement 类型, 默认为 PREPARED,可选值:STATEMENT,PREPARED 和 CALLABLE。 -

注意:update 标签中没有 resultType 属性,只有查询操作才需要对返回结果类型进行相应的指定。

MyBatis delete标签

MyBatis delete 标签用于定义 delete 语句,执行删除操作。当 MyBatis 执行完一条更新语句后,会返回一个整数,表示受影响的数据库记录的行数。

下面我们通过一个示例演示 delete 标签的用法。

BlogMapper.xml

<delete id="deleteBlogById" parameterType="int">
    delete from blog where id=#{id};
</delete>

BlogMapper

 int deleteBlogById(int id);

MainApplication

BlogMapper mapper = session.getMapper(BlogMapper.class);
// 你的应用逻辑代码
int i =  mapper.deleteBlogById(1);
System.out.println("共删除了 " + i + " 条记录");

delete 标签常用属性

delete 标签常用属性如下表。

属性名称 描述 备注
id 它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用 如果命名空间+ id 不唯一,那么 MyBatis 抛出异常
parameterType 传入 SQL 语句的参数类型的全限定名或别名,它是一个可选属性。 支持基本数据类型和 JavaBean、Map 等复杂数据类型
flushCache 该属性用于设置执行该操作后,是否会清空二级缓存和本地缓存,默认值为 true。 -
timeout 该属性用于设置 SQL 执行的超时时间,如果超时,就抛异常。 -
statementType 执行 SQL 时使用的 statement 类型, 默认为 PREPARED,可选值:STATEMENT,PREPARED 和 CALLABLE。 -

注意:delete 标签中没有 resultType 属性,只有查询操作才需要对返回结果类型进行相应的指定。

posted @ 2021-12-17 16:34  青杉  阅读(136)  评论(0编辑  收藏  举报