首页 > 其他分享 >MyBatis从入门到面试:超全

MyBatis从入门到面试:超全

时间:2024-08-13 19:23:23浏览次数:11  
标签:Mapper 超全 SqlSession session SQL MyBatis id 入门

MyBatis从入门到面试

MyBatis启动!!!

1.引入依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.13</version> <!-- 版本号可以根据需要进行调整 -->
</dependency>

1. 配置文件

首先,我们需要一个 MyBatis 配置文件,通常命名为 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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydatabase"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

2. Mapper XML 文件

接下来,我们需要一个 Mapper XML 文件( UserMapper.xml),它定义了 SQL 语句和映射规则。

<?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.example.mapper.UserMapper">

    <select id="selectUser" resultType="com.example.model.User">
        SELECT id, name, email FROM users WHERE id = #{id}
    </select>

    <insert id="insertUser">
        INSERT INTO users (name, email) VALUES (#{name}, #{email})
    </insert>

    <update id="updateUser">
        UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
    </update>

    <delete id="deleteUser">
        DELETE FROM users WHERE id = #{id}
    </delete>

</mapper>

3. 实体类

我们还需要一个与数据库表映射的实体类(如 User.java)。

package com.example.model;

public class User {
    private int id;
    private String name;
    private String email;

    // Getters and setters
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

4. Mapper 接口

MyBatis 提供了通过接口来访问数据库的方式,我们定义一个 Mapper 接口(如 UserMapper.class),如果在注解中定义了sql语句就可以不用再在对应的xml文件中定义。

package com.example.mapper;

import com.example.model.User;
import org.apache.ibatis.annotations.*;

public interface UserMapper {

    @Select("SELECT id, name, email FROM users WHERE id = #{id}")
    User selectUser(int id);

    @Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
    void insertUser(User user);

    @Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")
    void updateUser(User user);

    @Delete("DELETE FROM users WHERE id = #{id}")
    void deleteUser(int id);
}

5. MyBatis 操作

我们现在可以使用 MyBatis 进行数据库操作。下面是一个使用 MyBatis 进行基本 CRUD 操作的示例代码。

package com.example;

import com.example.mapper.UserMapper;
import com.example.model.User;
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;

public class MyBatisExample {

    public static void main(String[] args) throws IOException {
        // 1. 读取 MyBatis 配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 2. 构建 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 3. 获取 SqlSession
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 4. 获取 Mapper
            UserMapper mapper = session.getMapper(UserMapper.class);

            // 5. 插入新用户
            User newUser = new User();
            newUser.setName("John Doe");
            newUser.setEmail("[email protected]");
            mapper.insertUser(newUser);
            session.commit();

            // 6. 查询用户
            User user = mapper.selectUser(1);
            System.out.println("User: " + user.getName() + ", Email: " + user.getEmail());

            // 7. 更新用户
            user.setName("Jane Doe");
            mapper.updateUser(user);
            session.commit();

            // 8. 删除用户
            mapper.deleteUser(user.getId());
            session.commit();
        }
    }
}

6. 执行流程总结

  1. 配置环境:MyBatis 通过 mybatis-config.xml 配置文件读取数据库连接和其他相关配置。
  2. 定义映射关系:Mapper XML 文件中定义了 SQL 语句和 Java 对象之间的映射关系。
  3. 创建实体类:实体类用于表示数据库中的表结构。
  4. 创建 Mapper 接口:Mapper 接口定义了操作数据库的各种方法,MyBatis 自动生成其实现。
  5. 执行操作:通过 SqlSession 获取 Mapper 接口实例,然后调用接口方法执行 SQL 操作。

目录结构如下:
目录结构
整个流程跑完一遍,MyBatis差不多就上手了


Mybatis原理

1. 初始化 MyBatis

MyBatis 的初始化从读取配置文件开始,创建 SqlSessionFactory,它负责产生 SqlSession

1.1 读取配置文件

MyBatis 的配置文件通过 SqlSessionFactoryBuilder 进行解析和构建:

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSessionFactoryBuilder 解析完XML 配置文件,会创建一个 Configuration 对象,保存所有的配置信息。其中XMLConfigBuilder 是用来解析配置文件的核心类,负责将 XML 文件转换成 MyBatis 的内存配置。

public SqlSessionFactory build(InputStream inputStream) {
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream);
        Configuration config = parser.parse();
        return build(config);
    } finally {
        ErrorContext.instance().reset();
        try {
            inputStream.close();
        } catch (IOException e) {
            // Ignore close exception
        }
    }
}
1.2 创建 SqlSessionFactory

然后通过构建的configuration对象来构建一个SqlSessionFactory
SqlSessionFactory是Mybatis中的一个核心接口,用于构建SqlSession

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

2. 创建 SqlSession

利用创建好的SqlSessionFactory来建立SqlSession
SqlSession 是 MyBatis 执行 SQL 的接口。每次操作数据库都需要通过 SqlSession 来完成。

try (SqlSession session = sqlSessionFactory.openSession()) {
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.selectUser(1);
}

SqlSession 实际上是通过 Configuration 对象来初始化的,它内部封装了执行器(Executor),通过 Executor 来执行所有的 SQL 语句。

3. 获取 Mapper 接口代理对象

建立好了会话就可以通过传入接口类型来获取相应的接口代理对象
MyBatis 通过 MapperProxy 动态代理生成 Mapper 接口的实现类。MapperProxyFactory 会为每一个 Mapper 创建一个代理对象。

UserMapper mapper = session.getMapper(UserMapper.class);

getMapper 方法背后的实现是通过 JDK 动态代理来完成的:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, new MapperProxy<>(sqlSession, mapperInterface, methodCache));
}

MapperProxy 实现了 InvocationHandler 接口,当调用 Mapper 接口的方法时,invoke 方法会被执行。

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
}

4. 执行 SQL

使用生成的代理对象中的方法来执行SQL
执行 SQL 是 MyBatis 核心操作之一,MapperMethod 类封装了 SQL 的执行过程。每次调用 Mapper 接口的代理的方法,都会通过 MapperMethod 进行实际的 SQL 执行。
具体的说:
MapperMethod 会解析 Mapper 接口的方法签名,确定对应的 SQL 语句类型(如 SELECT、INSERT、UPDATE、DELETE),以及方法的参数类型和返回值类型,并绑定方法传入参数。

public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
        case INSERT: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.insert(command.getName(), param));
            break;
        }
        case UPDATE: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.update(command.getName(), param));
            break;
        }
        case DELETE: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.delete(command.getName(), param));
            break;
        }
        case SELECT:
            if (method.returnsVoid() && method.hasResultHandler()) {
                executeWithResultHandler(sqlSession, args);
                result = null;
            } else if (method.returnsMany()) {
                result = executeForMany(sqlSession, args);
            } else if (method.returnsMap()) {
                result = executeForMap(sqlSession, args);
            } else if (method.returnsCursor()) {
                result = executeForCursor(sqlSession, args);
            } else {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = sqlSession.selectOne(command.getName(), param);
            }
            break;
        default:
            throw new BindingException("Unknown execution method for: " + command.getName());
    }
    return result;
}

5. SQL 语句的解析和执行

MapperMethod 解析出方法签名后,会根据方法的名称和接口的 namespace(命名空间)查找对应的 MappedStatement 对象。

MyBatis 使用 MappedStatement 对象表示一个完整的 SQL 语句,它包括 SQL 的定义、输入参数和输出结果的映射。

当执行 SQL 时,MyBatis 会通过 Executor 执行 SQL 语句。

@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
    return executor.update(ms, wrapCollection(parameter));
}

Executor 是 MyBatis 中的核心组件,负责执行 SQL 语句、事务管理和缓存管理。常见的 Executor 实现有 SimpleExecutorBatchExecutor

6. 结果集处理

MappedStatement通过 SqlSession 执行 SQL 语句后,会获得一个 ResultSet 对象。此时会调用 ResultSetHandler 来处理这个 ResultSet

ResultSetHandler 会遍历 ResultSet,根据 MappedStatement 中的 ResultMap 配置,将每一行数据映射为对应的 Java 对象。处理的过程包括:

  • 将 ResultSet 中的列值映射到 Java 对象的属性中
  • 处理关联关系(如一对多、一对一等),并将结果集转换为嵌套的对象结构。
    返回结果:

ResultSetHandler 处理完结果集后,会将转换后的对象或对象集合返回给 SqlSessionSqlSession 再将这些结果返回给 MapperMethod
最终,MapperMethod 将结果返回给调用者。

public <E> List<E> handleResultSets(Statement stmt) throws SQLException {
    try {
        List<E> multipleResults = new ArrayList<>();
        ResultSet rs = stmt.getResultSet();
        handleResultSet(rs, multipleResults);
        return collapseSingleResultList(multipleResults);
    } finally {
        closeResultSet(rs);
    }
}

总结

MyBatis 的执行流程可以总结为以下几个步骤:

  1. 初始化:通过 SqlSessionFactoryBuilder 读取配置文件,创建 SqlSessionFactory
  2. 创建 SqlSession:通过 SqlSessionFactory 创建 SqlSession
  3. 获取 Mapper:通过动态代理获取 Mapper 接口的实现类。
  4. SQL语句映射:通过MapperMethod方法找到对应的MappedStateMent,将查询java对象映射到 SQL语句中并使用Executor执行。
  5. 结果映射:将 SQL 查询结果通过 ResultSetHandler 映射为 Java 对象。

面试

1. 什么是 MyBatis?它与其他 ORM 框架(如 Hibernate)有什么不同?

解答
MyBatis 是一个开源的持久层框架,它通过 XML 或注解的方式将对象映射到 SQL 语句。与 Hibernate 等全功能的 ORM 框架相比,MyBatis 主要是一个半自动化的 SQL 映射框架,它允许开发者在 SQL 语句中控制更大的灵活性和优化空间。

  • 主要区别
    • 控制性:MyBatis 允许开发者直接编写 SQL 语句,而 Hibernate 等 ORM 框架通常是通过对象模型来生成 SQL。
    • 性能:MyBatis 适合复杂的查询或需要优化的场景,开发者可以直接优化 SQL 语句。
    • 学习曲线:MyBatis 学习曲线较低,尤其对于熟悉 SQL 的开发者来说。

2. MyBatis 的核心配置文件 mybatis-config.xml 中有哪些常见的配置项?

解答
mybatis-config.xml 是 MyBatis 的核心配置文件,常见的配置项包括:

  • <settings>:全局配置,如缓存、驼峰命名等。
  • <typeAliases>:设置类型别名,简化 Java 类的引用。
  • <plugins>:配置插件,扩展 MyBatis 的功能。
  • <environments>:配置数据库连接信息,可以定义多种环境(如开发、测试、生产)。
  • <mappers>:配置 Mapper 的位置,可以使用 XML 或注解。

示例:

<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <typeAliases>
        <typeAlias type="com.example.model.User" alias="User"/>
    </typeAliases>
    <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/mydb"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

3. MyBatis 中的 Mapper 接口是什么?如何使用?

解答
Mapper 接口是 MyBatis 的核心部分,用于定义数据库操作的方法。MyBatis 会通过动态代理生成这些接口的实现类。可以使用注解或 XML 来定义 SQL 语句。

使用步骤

  1. 定义 Mapper 接口
public interface UserMapper {
    User selectUserById(@Param("id") int id);
    void insertUser(User user);
}
  1. 配置 Mapper 文件(可以选择 XML 或注解方式):

XML 配置示例

<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectUserById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    <insert id="insertUser">
        INSERT INTO users (name, email) VALUES (#{name}, #{email})
    </insert>
</mapper>
  1. 使用 Mapper 接口
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectUserById(1);
session.commit();
session.close();

4. 如何处理 MyBatis 中的事务?

解答
MyBatis 支持事务管理,可以通过 SqlSession 来手动控制事务。事务的管理方式包括:

  • 手动管理事务
    • 通过 SqlSession 开始、提交或回滚事务。

示例:

SqlSession session = sqlSessionFactory.openSession();
try {
    UserMapper userMapper = session.getMapper(UserMapper.class);
    userMapper.insertUser(new User("John", "[email protected]"));
    session.commit(); // 提交事务
} catch (Exception e) {
    session.rollback(); // 回滚事务
} finally {
    session.close(); // 关闭会话
}
  • 自动管理事务
    • 如果使用 Spring 等框架,可以通过 Spring 的事务管理来控制 MyBatis 的事务,通常使用注解或 XML 配置。

5. MyBatis 中的 ResultMap 是什么?如何使用?

解答
ResultMap 是 MyBatis 中用于定义结果集与 Java 对象之间映射关系的配置。它允许对复杂的结果集进行灵活的映射。

示例

<resultMap id="userResultMap" type="User">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="email" column="email"/>
</resultMap>

<select id="selectUserById" resultMap="userResultMap">
    SELECT * FROM users WHERE id = #{id}
</select>

在这个例子中,ResultMap 定义了 User 对象的属性与数据库列之间的映射关系。


6. MyBatis 中的分页如何实现?

解答
MyBatis 本身不提供分页功能,但可以通过插件或手动实现分页。常用的方式是使用 RowBounds 或第三方分页插件(如 MyBatis-PageHelper)。

使用 RowBounds

List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.selectAll", null, new RowBounds(offset, limit));

使用 PageHelper

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.1</version>
</dependency>
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.selectAll();

7. MyBatis 中的 SqlSessionFactorySqlSession 是什么?它们有什么区别?

解答

  • SqlSessionFactory:是 MyBatis 的核心工厂类,用于创建 SqlSession 实例。它由 SqlSessionFactoryBuilder 创建,并负责管理 MyBatis 的配置(如 mybatis-config.xml)。

  • SqlSession:是 MyBatis 中用于执行 SQL 语句的接口。每个 SqlSession 实例表示一个数据库会话,通常用于执行 SQL 语句、获取 Mapper 实例、管理事务等。

区别

  • SqlSessionFactory 是线程安全的单例,负责管理配置和创建 SqlSession
  • SqlSession 是非线程安全的,每个数据库操作应使用一个新的 SqlSession

示例

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

8. MyBatis 的延迟加载(Lazy Loading)是如何实现的?

解答
MyBatis 的延迟加载允许在需要时才加载某些属性或关联对象,以减少不必要的数据库查询。延迟加载有两种主要方式:

  • 延迟加载单个对象:可以通过在映射文件中设置 fetchTypeLAZY,指定某个属性在需要时才加载。

  • 延迟加载集合:通常通过 CollectionMap 映射配置来实现。

示例

<association property="department" javaType="Department" fetchType="lazy">
    <id property="id" column="department_id"/>
    <result property="name" column="department_name"/>
</association>

在这个例子中,department 属性将被设置为懒加载,只有在实际访问时才会查询数据库。


9. MyBatis 中如何使用动态 SQL?

解答
动态 SQL 允许根据不同的条件动态生成 SQL 语句。MyBatis 提供了多个动态 SQL 标签:

  • <if>:条件判断
  • <choose>:类似于 SQL 的 CASE
  • <foreach>:遍历集合
  • <where>:自动添加 WHERE 关键字
  • <trim>:对 SQL 语句进行修剪

示例

<select id="selectUser" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">
            AND name = #{name}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
</select>

这个示例会根据 nameemail 的值动态生成 SQL 查询。


10. MyBatis 中的缓存机制具体如何工作?

解答
MyBatis 提供了一级缓存和二级缓存机制:

  • 一级缓存SqlSession 范围内的缓存。每个 SqlSession 都有一个独立的缓存,默认启用。相同的 SQL 查询在同一个 SqlSession 内会被缓存。

  • 二级缓存SqlSessionFactory 范围内的缓存。允许跨多个 SqlSession 共享缓存,需要在 XML 配置中开启,并设置缓存实现(如 Ehcache、Redis)。

  • 缓存更新:当某个作用域中发生更新,插入,删除,默认该作用域下的所有select缓存会被清空。

示例

二级缓存 XML 配置

<cache type="org.apache.ibatis.cache.decorators.FifoCache"/>

Mapper XML 配置

<mapper namespace="com.example.mapper.UserMapper" useCache="true">
    <cache/>
    <select id="selectUserById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
</mapper>

11. MyBatis 中的 @SelectProvider, @InsertProvider, @UpdateProvider, @DeleteProvider 注解的作用是什么?

解答
这些注解用于动态生成 SQL 语句,通过指定一个 Provider 类的方法来提供 SQL 语句。Provider 类负责根据方法参数生成 SQL。

  • @SelectProvider:用于动态生成 SELECT 语句。
  • @InsertProvider:用于动态生成 INSERT 语句。
  • @UpdateProvider:用于动态生成 UPDATE 语句。
  • @DeleteProvider:用于动态生成 DELETE 语句。

示例

@SelectProvider(type = UserSqlProvider.class, method = "selectUserById")
User selectUserById(int id);

Provider 类示例

public class UserSqlProvider {
    public String selectUserById(int id) {
        return "SELECT * FROM users WHERE id = " + id;
    }
}

12. 如何在 MyBatis 中处理批量操作?

解答
MyBatis 支持批量操作,通过 SqlSession 的批量方法(如 insertupdatedelete)可以在同一个事务中执行多条 SQL 语句。

示例

SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
    UserMapper mapper = session.getMapper(UserMapper.class);
    for (User user : users) {
        mapper.insertUser(user);
    }
    session.commit();
} finally {
    session.close();
}

在这个示例中,所有的 insertUser 操作会在一个批量操作中执行,以提高效率。


13. MyBatis 中的 ResultHandler 是什么?

解答
ResultHandler 用于处理查询结果,可以在 SQL 查询返回结果时自定义处理逻辑。它通常用于需要逐行处理结果的场景。

示例

public class MyResultHandler implements ResultHandler<User> {
    @Override
    public void handleResult(ResultContext<? extends User> resultContext) {
        User user = resultContext.getResultObject();
        // 自定义处理逻辑
    }
}

// 使用示例
List<User> users = new ArrayList<>();
sqlSession.select("com.example.mapper.UserMapper.selectAll", null, new MyResultHandler());

14. MyBatis 中如何处理数据库的不同类型(如 MySQL、Oracle)?

解答
MyBatis 支持多种数据库类型,通过配置不同的 JDBC 驱动程序和数据源来处理不同的数据库。需要在 mybatis-config.xml 文件中配置正确的数据源和事务管理器。

示例

<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/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </dataSource>
</environment>

如果需要支持不同类型的数据库,可以创建不同的配置文件和数据源,然后在不同的环境中切换。


15. MyBatis 的 SqlSession 的生命周期管理是怎样的?

解答
SqlSession 的生命周期通常由开发者控制,主要包括以下几个步骤:

  1. 打开 SqlSession:通过 SqlSessionFactory 创建 SqlSession 实例。
  2. 使用 SqlSession:执行 SQL 操作、获取 Mapper 实例等。
  3. 提交或回滚事务:在完成操作后,通过 commit() 提交事务,或者在异常情况下通过 rollback() 回滚事务。
  4. 关闭 SqlSession:完成所有操作后,关闭 SqlSession 实例以释放资源。

16. #{}${} 的区别是什么?

解答

#{}${} 是 MyBatis 中用来处理参数的两种不同方式,它们的主要区别在于参数的处理方式和使用场景。

  1. #{}(预编译参数占位符):

    • #{} 是用来传递参数到 SQL 语句中的预编译占位符。
    • 使用 #{} 时,MyBatis 会将参数安全地传递到 SQL 中,避免 SQL 注入风险。
    • MyBatis 在执行 SQL 语句时,会使用 JDBC 的 PreparedStatement,将参数作为查询参数绑定,从而确保输入被安全处理。

    示例

    <select id="selectUserById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    
  2. ${}(字符串替换占位符):

    • ${} 是用来进行字符串替换的占位符。
    • 使用 ${} 时,MyBatis 会直接将参数的值替换到 SQL 语句中,这种方式没有预编译,因此更容易受到 SQL 注入的攻击。
    • ${} 通常用于动态拼接 SQL 片段,如表名、列名等。

    示例

    <select id="selectUser" resultType="User">
        SELECT * FROM ${tableName} WHERE id = #{id}
    </select>
    

17. 如何在 MyBatis 中处理多表关联查询?

  • 回答:可以通过 ResultMap 的方式处理多表关联查询。假设有用户表和订单表,可以通过以下方式进行一对多的关联映射:
    <resultMap id="userResultMap" type="User">
      <id property="id" column="user_id"/>
      <result property="name" column="name"/>
      <collection property="orders" ofType="Order">
        <id property="id" column="order_id"/>
        <result property="amount" column="amount"/>
      </collection>
    </resultMap>
    
    <select id="findUserWithOrders" resultMap="userResultMap">
      SELECT u.user_id, u.name, o.order_id, o.amount 
      FROM users u 
      LEFT JOIN orders o ON u.user_id = o.user_id
      WHERE u.user_id = #{userId}
    </select>
    

标签:Mapper,超全,SqlSession,session,SQL,MyBatis,id,入门
From: https://blog.csdn.net/bobplease/article/details/141154275

相关文章

  • MyBatis基本流程
    MyBatis基本流程基本使用步骤准备数据CREATEDATABASE`mybatis-example`;​USE`mybatis-example`;​CREATETABLE`t_emp`(emp_idINTAUTO_INCREMENT,emp_nameCHAR(100),emp_salaryDOUBLE(10,5), PRIMARYKEY(emp_id));​INSERTINTO`t_emp`(emp_na......
  • Mybatis基本使用
    Mybatis基本使用1.日志输出在mybatis-config.xml中的settings标签配置mybatis的设置项<settings>  <settingname="logImpl"value="STDOUT_LOGGING"/></settings>设置日志的属性是logImpl,其候选值有SLF4J、LOG4J、LOG4J2、STDOUT_LOGGING、NOLOGGING等 2.......
  • Deno-入门指南-全-
    Deno入门指南(全)原文:IntroducingDeno协议:CCBY-NC-SA4.0一、为什么是Deno?在过去的10年里,当后端开发人员听到“后端的JavaScript”这个词时,所有人都会立即想到Node.js。在这10年的开始,也许不会马上出现,但最终它的名字为每个人所知,成为另一种基于JavaScript的可用......
  • 2024最新最全【AIGC】学习零基础入门到精通,看完这一篇就够了!
    AIGC(AI-GeneratedContent)即人工智能生成内容,是指利用人工智能技术来创造各种形式的内容,包括文字、图像、视频、音频和游戏等。与专业生成内容(PGC)和用户生成内容(UGC)相对应,AIGC代表着内容生产方式的演进,其生产速度以指数级增长。为什么要学习AIGC?根据猎聘大数据研究院发布......
  • vue3+three入门一
    <scriptsetuplang="ts">import*asTHREEfrom'three';import{onMounted,ref}from"vue";import{ArcballControls}from"three/examples/jsm/controls/ArcballControls";constcontainerRef=ref(null)const......
  • 【产品经理修炼之道】- 优惠券系统从入门到精通(四十五)
    在高并发情况下我是这样解决单用户超领优惠券问题问题抛出在近期的项目里面有一个功能是领取优惠券的功能,问题描述:每一个优惠券一共发行多少张,每个用户可以领取多少张:如:A优惠券一共发行120张,每一个用户可以领取140张,当一个用户领取优惠券成功的时候,把领取的记录写入到另......
  • 算法入门
    首先,了解一下集成学习及Boosting算法。集成学习归属于机器学习,他是一种“训练思路”,并不是某种具体的方法或者算法。现实生活中,大家都知道“人多力量大”,“3个臭皮匠顶个诸葛亮”。而集成学习的核心思路就是“人多力量大”,它并没有创造出新的算法,而是把已有的算法进行结合,从而......
  • 【图像去噪】论文复现:新手入门必看!DnCNN的Pytorch源码训练测试全流程解析!为源码做详细
    第一次来请先看【专栏介绍文章】:源码只提供了noiselevel为25的DnCNN-S模型文件。本文末尾有完整代码和训练好的σ=15,25,50的DnCNN-S、σ∈[0,55]的DnCNN-B和CDnCNN-B、DnCNN-3共6个模型文件!读者可以自行下载!本文亮点:以官方Pytorch源代码为基础,在DnCNN-S的基础上,增添Dn......
  • 游戏安全入门-扫雷分析&远程线程注入
    前言无论学习什么,首先,我们应该有个目标,那么入门windows游戏安全,脑海中浮现出来的一个游戏--扫雷,一款家喻户晓的游戏,虽然已经被大家分析的不能再透了,但是我觉得自己去分析一下还是极好的,把它作为一个小目标再好不过了。我们编写一个妙妙小工具,工具要求实现以下功能:时间暂停、修......
  • 用了MyBatis-PLUS的项目 如何优雅的打印SQL
    说明在使用MyBatis-Plus作为ORM框架的时候,会发现默认的日志输出是下面这样的:在参数少并且SQL简单的情况下,这样的SQL我们能通过手动去替换占位符,来获取到真正执行的SQL。但是如果是比较复杂的SQL,或者查询参数比较多的话,一个个替换就比较费时费力了。我们可以通过实现com.baomid......