MyBatis基础学习
这里直接介绍基础使用,使用SSM整合后的基础使用,不在讲述mybatis的xml配置。
使用MyBatis需要导入依赖坐标
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
1. Mapper代理开发
-
定义与SQL映射文件同名的mapper接口,并且将mapper接口和SQL映射文件放置在统一目录下。
-
设置SQL映射文件的namescape属性为mapper接口全限定名。
设置 SQL 映射文件的 namespace 属性为 Mapper 接口的全限定名的作用是:
- 关联 Mapper 接口与 SQL 映射文件:通过设置 namespace 属性,可以将 Mapper 接口与对应的 SQL 映射文件关联起来。这样,MyBatis 在执行 Mapper 接口方法时,会根据 namespace 属性去查找对应的 SQL 映射文件,并执行其中定义的 SQL 语句。
- 提供命名空间:namespace 属性还可以为 SQL 映射文件提供一个命名空间,用于区分不同的 SQL 语句和操作。通过设置不同的 namespace 属性,可以将不同的 SQL 语句和操作进行分类和管理,提高代码的可维护性和可读性。
- 避免冲突:使用 Mapper 接口的全限定名作为 namespace 属性,可以避免不同的 Mapper 接口之间的方法名冲突。每个 Mapper 接口的方法名都应该是唯一的,通过设置不同的 namespace 属性,可以确保不同的 Mapper 接口之间的方法名不会产生冲突。
namespace直接指定对应的包名路径,找到对应的接口实现方法相互对应。
在IDEA中可以设置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="com.cqut.dao.BookDao">
</mapper>
- 在mapper接口中定义方法,方法名就是SQL映射文件sql语句的id,并保持参数类型和返回值类型一致。
2. 参数映射
MyBatis提供了ParamNameResolver
类来进行参数封装
-
POJO类型:直接使用,实体类属性名和参数占位符名称一致
-
Map集合:直接使用,键名和参数占位符名称一致
-
Colletion:封装成Map集合
map.put("collection", collection); map.put("arg0", collection);
-
List:封装为Map集合
map.put("collection", list); map.put("list", list); map.put("arg0", list);
-
Array:封装成Map集合
map.put("array", arg0); map.put("arg0", arg0);
-
其他类型执行使用
-
多个参数:封装成Map集合,分别指定由
arg0
和param0
两种形式对应一个值,通过@Param
注解来修改Map中param0
一类默认的键名,使用修改后的名称来获取键值。
- collection、list、array封装到map集合中,将其按键值取出,通过迭代器间集合/数组中的元素取出。
3. 结果映射
- mybatis可以自动映射查询结果,mybatis会获取结构中返回的列名并在java类中查找相同名字的属性(忽略大小写)。
- 通常数据库列使用大写字母组成的单词命名,单词间用下划线分隔,而Java属性一般遵循驼峰命名法约定,这样无法实现自动映射,需要手动映射。
<mapper namespace="com.cqut.dao.BookDao">
<resultMap id="bookResultMap" type="com.cqut.domain.Book">
<id property="id" column="ID"/>
<result property="name" column="NAME"/>
<result property="description" column="DESCRIPTION"/>
<result property="series" column="SERIES"/>
</resultMap>
<select id="selectById" resultMap="bookResultMap">
select * from tb_books where id = #{id};
</select>
</mapper>
在 MyBatis 中,ResultMap 是用于将查询结果集中的列与 Java 对象的属性进行映射的配置元素。ResultMap 可以使用以下标签来进行映射配置:
- id:用于指定 ResultMap 的唯一标识符,必须是全局唯一的。
- result:用于配置普通的属性映射关系,将查询结果集中的列与 Java 对象的属性进行映射。可以使用以下子标签:
- id:用于指定查询结果集中的列名。
- property:用于指定 Java 对象的属性名。
- association:用于配置关联对象的映射关系,将查询结果集中的列与关联对象的属性进行映射。可以使用以下子标签:
- id:用于指定关联对象的唯一标识符。
- resultMap:用于指定关联对象的 ResultMap 的引用。
- collection:用于配置集合属性的映射关系,将查询结果集中的列与集合属性的元素进行映射。可以使用以下子标签:
- id:用于指定集合属性的唯一标识符。
- resultMap:用于指定集合属性的元素的 ResultMap 的引用。
- discriminator:用于配置鉴别器的映射关系,根据查询结果集中的列的值来决定选择哪个 ResultMap 进行映射。可以使用以下子标签:
- column:用于指定查询结果集中的列名。
- javaType:用于指定鉴别器的 Java 类型。
- case:用于配置不同的鉴别值和对应的 ResultMap。
- constructor:用于配置构造函数的映射关系,将查询结果集中的列与构造函数的参数进行映射。可以使用以下子标签:
- idArg:用于指定构造函数的参数的映射关系。
- arg:用于指定构造函数的参数的映射关系。
4. 动态查询
4.1. 参数占位符
#{}
:执行SQL语句,将会使用#{}
占位符替换为?
,自动设置参数值。${}
:字符串拼接,存在SQL注入的问题。- 特殊字符处理:
- 转移字符:小于号
<
<![CDATA[内容]]>
- 转移字符:小于号
4.2. if标签
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
如果成立则最后的查询语句是
select * from bolg where state = 'active' and title like ?
否则是
select * from bolg where state = 'active'
4.3. choose(when, otherwise)标签
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
可以动态实现查询条件的变化
select * from bolg where state = 'active' and featured = 1
select * from bolg where state = 'active' and title like ?
select * from bolg where state = 'active' and author_name like ?
这里<choose>
相当于switch
,<when>
相当于case
,otherwise
相当于default
4.4. trim(where,set)标签
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
如上述查询语句,当第一个条件不成立或者全部条件都不成立,则会出现以下查询语句:
select * from blog where and title like ?
select * from blog where
SQL语法出项错误,mybatis中提供了<where>
标签来实现where
的功能
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
当出项上述两种错误形式,可以自动纠正
select * from blog where title like ?
select * from blog
<set>
也具有相同的功能修正SQL语法
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
会对结尾,
和空语句进行修正。当使用 <set>
元素时,MyBatis 会自动处理逗号的添加和位置,它会确保只在非第一个属性的更新语句之前添加逗号,并在最后一个属性的更新语句之后不添加逗号。
4.5. foreach标签
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
<where>
<foreach item="item" index="index" collection="list"
open="ID in (" separator="," close=")" nullable="true">
#{item}
</foreach>
</where>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
通过collection
属性取出对应键值对的集合/数组对象,在通过index
和item
来取得集合/数组中的值。
如果 List 是 List 类型,而 User 类中又有 username 和 password 属性,可以使用 <foreach>
标签来遍历 List,并将每个 User 对象的属性传递给 SQL 语句。(代码逻辑上可能有问题,主要是理解怎么集合怎么使用映射对象属性值)
// Java 方法
List<User> getUsers(List<User> userList);
<!-- Mapper XML -->
<select id="getUsers" resultType="User">
SELECT * FROM user WHERE 1=1
<foreach collection="userList" item="user" separator="AND">
username = #{user.username}
password = #{user.password}
</foreach>
</select>
5. 注解开发
SQL语句简单可以使用,复杂的推荐使用xml形式开发。
public interface BookDao {
@Insert("insert into tb_books (name, series, description) values(#{name}, #{series}, #{description})")
public int add(Book book);
@Delete("delete from tb_books where id = #{id}")
public int deleteById(int id);
@Update("update tb_books set name = #{name}, series = #{series}, description = #{description} where id = #{id}")
public int upDataById(Book book);
@Select("select * from tb_books where id = #{id};")
public Book selectById(int id);
@Select("select * from tb_books")
public List<Book> selectAll();
}