MyBatis(二)MyBatis标签
MyBatis 目录
- MyBatis(一)MyBatis初识 - 青杉 - 博客园 (cnblogs.com)
- MyBatis(二)MyBatis标签 - 青杉 - 博客园 (cnblogs.com)
- MyBatis(三)MyBatis resultMap和注解 - 青杉 - 博客园 (cnblogs.com)
- MyBatis(四)MyBatis关联(级联)查询 - 青杉 - 博客园 (cnblogs.com)
- MyBatis(五)MyBatis动态SQL - 青杉 - 博客园 (cnblogs.com)
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 | 它是映射集的引用,与 |
是 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 来模糊查询网站信息,显然这涉及到了两个参数。给映射器传递多个参数分为以下三种方法。
- 使用Map传递参数
- 使用注解传递参数
- 使用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 执行完一条插入语句后,就会返回其影响数据库的行数。
用法
-
修改 BlogMapper.xml,增加插入语句,代码如下。
<insert id="insertBlog"> insert into blog(`blog_title`,`desc`) values (#{blogTitle},#{desc}); </insert>
-
在 WebsiteMapper 接口中定义一个 add() 方法,代码如下。
int insertBlog(Blog blog);
-
测试代码如下。
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 + " 条记录");
-
输出
共插入了 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 等,表示数据库厂家;元素内部可通过 |
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 |
keyColumn | 该属性用于设置第几列是主键,当主键列不是表中的第 1 列时,就需要设置该属性。如果是联合主键,可以将多个值用逗号隔开。 | - |
注意:insert 标签中没有 resultType 属性,只有查询操作才需要对返回结果类型进行相应的指定。
主键(自动递增)回填
我们知道,MySQL、SQL Server 等数据库表可以采用自动递增的字段作为其主键,当向这样的数据库表插入数据时,即使不指定自增主键的值,数据库也会根据自增规则自动生成主键并插入到表中。
一些特殊情况下,我们可能需要将这个刚刚生成的主键回填到请求对象(原本不包含主键信息的请求对象)中,供其他业务使用。此时,我们就可以通过在 insert
标签中添加 keyProperty
和 useGeneratedKeys
属性,来实现该功能。
下面我们通过一个示例,来演示主键(自动递增)回填功能。
-
为
BlogMapper.xml
中 id 为insertBlog
的insert
标签添加keyProperty
和useGeneratedKeys
属性,具体代码如下:<insert id="insertBlog" parameterType="org.mybatis.example.Blog" keyProperty="id" useGeneratedKeys="true"> insert into blog(`blog_title`,`desc`) values (#{blogTitle},#{desc}); </insert>
-
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());
-
输出
共插入了 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 属性,只有查询操作才需要对返回结果类型进行相应的指定。