MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs (Plain Old Java Objects, 普通的 Java 对象)映射成数据库中的记录。
以下是 MyBatis 的主要特点:
以下是如何在 Spring Boot 项目中使用 MyBatis 的详细步骤和示例
首先,你需要在你的 pom.xml
文件中添加 MyBatis 和 MyBatis-Spring 的依赖。
<dependencies>
<!-- other dependencies -->
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
在 application.properties
或 application.yml
中配置数据源信息。
# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=rootpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
创建一个实体类来表示数据库中的表。例如,一个用户实体类 User
:
public class User {
private Long id;
private String name;
private String email;
// getters and setters ...
}
创建一个接口来定义对数据库的操作。使用 MyBatis 的注解来定义 SQL 语句。例如,一个 UserMapper
:
import org.apache.ibatis.annotations.*;
import java.util.List;
import static org.apache.ibatis.annotations.Select.*;
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(Long id);
@Select("SELECT * FROM users")
List<User> getAllUsers();
}
你可以在你的 Service 或 Controller 中注入 UserMapper
并使用它。例如,在一个简单的 UserService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import static org.springframework.transaction.annotation.Transactional;
import static org.springframework.transaction.annotation.Propagation.*;
@Service("userService")
@Transactional(propagation = REQUIRED)
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Long id) {
return userMapper.getUserById(id);
}
public List<User> getAllUsers() {
return userMapper.getAllUsers();
}
}
MyBatis 在 XML 文件中定义 SQL 语句时,主要使用以下元素:
<mapper>
:映射器,通常作为根元素使用,它允许你为 SQL 语句定义一个命名空间。<select>
:查询语句,用于从数据库中检索数据。<insert>
:插入语句,用于向数据库中插入数据。<update>
:更新语句,用于更新数据库中的数据。<delete>
:删除语句,用于从数据库中删除数据。下面是一个详细的示例,展示如何在 MyBatis 的 XML 文件中定义 SQL 语句:
<!-- 定义一个名为 "userMapper" 的映射器 -->
<mapper namespace="com.example.UserMapper">
<!-- 查询用户信息 -->
<select id="getUserById" parameterType="Long" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
<!-- 查询所有用户信息 -->
<select id="getAllUsers" resultType="User">
SELECT * FROM users
</select>
<!-- 插入用户信息 -->
<insert id="insertUser" parameterType="User">
INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="User">
UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
</update>
<!-- 删除用户信息 -->
<delete id="deleteUser" parameterType="Long">
DELETE FROM users WHERE id = #{id}
</delete>
</mapper>
在上述示例中,我们定义了一个名为 “userMapper” 的映射器,并在其中定义了多个 SQL 语句。每个 SQL 语句都有一个唯一的标识符(如 “getUserById”、“getAllUsers” 等),以及参数类型和结果类型。这些 SQL 语句可以在 Java 代码中被调用,以执行相应的数据库操作。
MyBatis 的动态 SQL 语法允许你在 XML 映射文件中根据参数条件动态地构建 SQL 查询。它通过使用 <if>
、<choose>
、<when>
、<otherwise>
等元素来构建可变的 SQL 查询。
示例:
<select id="findUsers" resultType="User">
SELECT * FROM users
WHERE 1 = 1
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
在上面的示例中,如果 name
和 email
参数不为 null
,它们会被包含在最终的 SQL 语句中。
示例:
<select id="findUsersByCriteria" resultType="User">
SELECT * FROM users
WHERE 1 = 1
<choose>
<when test="name != null">
AND name = #{name}
</when>
<when test="email != null">
AND email = #{email}
</when>
<otherwise>
AND status = 'ACTIVE'
</otherwise>
</choose>
</select>
在上面的示例中,根据参数的条件,选择相应的查询条件。如果 name
不为 null
,则包含 name 查询条件;如果 email
不为 null
,则包含 email 查询条件;否则,包含默认的查询条件。
WHERE
子句,避免多余的 AND
或 OR
关键字。示例:
<select id="findUsers" resultType="User">
SELECT * FROM users
<trim prefix="WHERE" prefixOverrides="AND | OR ">
<if test="name != null">AND name = #{name}</if>
<if test="email != null">AND email = #{email}</if>
</trim>
</select>
在上面的示例中,如果 name
和 email
都为 null
,则最终的 SQL 将不包含 WHERE
子句;如果任一参数不为 null
,则相应的查询条件将被添加到 WHERE
子句中。使用 <trim>
和 <where>
可以避免多余的 AND
或 OR
关键字。
<if>
元素和 <trim>
元素,以根据提供的参数动态地构建 SET 子句。<!-- 使用 <set> 元素构建动态 SET 子句 -->
<update id="updateUsers" parameterType="map">
UPDATE users
<set>
<if test="name != null">name = #{name},</if>
<if test="email != null">email = #{email},</if>
<if test="phone != null">phone = #{phone},</if>
</set>
WHERE id = #{id}
</update>
在上面的示例中,<set>
元素用于构建动态的 SET 子句。根据提供的参数(name
、email
和 phone
),只有非 null
的参数才会被包含在 SET 子句中。注意,我们在每个条件后面添加了一个逗号(,
),以确保生成的 SQL 是正确的。
<select>
、<insert>
和 <update>
元素一起使用,以处理集合或数组参数。<!-- 使用 <foreach> 元素迭代集合 -->
<insert id="insertUsers" parameterType="list">
INSERT INTO users (id, name, email, phone)
VALUES
<foreach collection="list" item="user" separator=",">
(#{user.id}, #{user.name}, #{user.email}, #{user.phone})
</foreach>
</insert>
<!-- 定义结果集映射 -->
<resultMap id="userResultMap" type="User">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="phone" column="phone" />
</resultMap>
<!-- 使用 <foreach> 元素迭代集合进行查询 -->
<select id="getUsersByList" resultMap="userResultMap">
SELECT * FROM users
WHERE id IN
<foreach collection="list" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</select>
在上面的<foreach>
示例中,<foreach>
元素用于迭代集合。在 <foreach>
元素中,我们指定了集合的名称(list
)、每个元素的别名(user
)和元素之间的分隔符(,
)。然后,我们使用 #{user.id}
、#{user.name}
等语法来引用每个元素的属性。最后,我们将每个插入语句以逗号分隔的形式列出。
在上面的<select>
示例中:
userResultMap
,用于将查询结果映射到 User
类型的 Java 对象。<select>
元素中,我们使用 <foreach>
元素来迭代传入的集合参数 list
。<foreach>
元素的属性指定了集合的名称(list
)、每个元素的别名(userId
)和元素之间的分隔符(,
)。在 <foreach>
元素内部,我们使用 #{userId}
来引用每个元素的属性。IN
子句使用了 <foreach>
元素生成的子查询,以匹配传入的集合中的用户ID。<resultMap>
元素来完成。<!-- 定义结果集映射 -->
<resultMap id="userResultMap" type="User">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="phone" column="phone" />
</resultMap>
<!-- 使用结果集映射进行查询 -->
<select id="getUserById" resultMap="userResultMap">
SELECT id, name, email, phone FROM users WHERE id = #{id}
</select>
在上面的示例中:
userResultMap
的结果集映射。该映射指定了 Java 对象的属性与数据库表的列之间的对应关系。通过 <id>
元素指定主键列,并通过 <result>
元素指定其他列。<select>
元素中,我们使用 resultMap
属性引用了之前定义的结果集映射 userResultMap
。这样,查询结果将根据该映射进行映射,并将查询结果转换为 User
类型的 Java 对象。<join>
元素来定义多表联接查询。<table alias="user">
可以使你使用 user.column_name
来引用列。@Select
、@Insert
、@Update
和 @Delete
注解可以直接在接口方法上定义 SQL 语句。${}
可以用于直接插入变量值。但是要注意,为了防止 SQL 注入攻击,建议仅在已知安全的上下文中使用 ${}
。通常,建议使用 #{}
来传递参数。PageHelper
和 MyBatis-Plus
,它们提供了方便的分页功能。src/main/resources/mybatis/mapper
目录下,与对应的接口位于同一包中。