首页 > 编程语言 >Java高手的30k之路|面试宝典|精通MyBatis(一)

Java高手的30k之路|面试宝典|精通MyBatis(一)

时间:2024-07-01 23:58:34浏览次数:20  
标签:Mapper Java 映射 SqlSession 30k SQL MyBatis id

基础知识

架构图

MyBatis的基本架构图,展示MyBatis核心组件及其相互关系:

Configuration mybatis-config.xml SqlSessionFactory Mapper XML SqlSession Annotations MyBatis SqlSessionFactoryBuilder Executor Cache Transaction StatementHandler ParameterHandler ResultSetHandler Database

解释

  • MyBatis:MyBatis框架的核心。
  • SqlSessionFactoryBuilder:用于创建SqlSessionFactory的构建器。
  • SqlSessionFactory:用于创建SqlSession的工厂。
  • SqlSession:表示与数据库的一次会话,用于执行SQL命令。
  • Executor:执行器,负责执行具体的SQL语句。
  • Cache:缓存机制,用于提升查询性能。
  • Transaction:事务管理,确保数据库操作的一致性。
  • StatementHandler:处理SQL语句的执行。
  • ParameterHandler:处理SQL语句的参数。
  • ResultSetHandler:处理SQL查询的结果集。
  • Database:实际的数据库,存储应用数据。

配置部分

  • mybatis-config.xml:MyBatis的全局配置文件。
  • Mapper XML:定义SQL语句和映射规则的XML文件。
  • Annotations:通过注解配置SQL语句和映射关系。

核心功能

MyBatis 的核心功能主要包括以下几个方面:

  1. SQL 映射:允许开发者在 XML 文件或 Java 注解中编写 SQL 语句,并将这些 SQL 与 Java 方法绑定。这为 SQL 提供了清晰的组织结构和可重用性,同时保持了 SQL 的灵活性。

  2. 参数映射:自动将 Java 方法的参数转换为 SQL 语句中的参数。MyBatis 支持多种参数类型和复杂的映射规则,使得参数传递变得简单且灵活。

  3. 结果映射:将查询结果自动映射到 Java 对象(POJOs,即 Plain Old Java Objects),无需手动处理结果集。MyBatis 支持复杂的映射关系,包括一对一、一对多和多对多关联映射。

  4. 动态 SQL:支持在 SQL 语句中嵌入条件逻辑,如 ifchoosewhenotherwisewhereset 等标签,使得 SQL 语句可以根据传入参数动态改变,提高了 SQL 的复用性和灵活性。

  5. 事务管理:MyBatis 提供了对事务的简单管理,可以通过 SqlSession 来提交或回滚事务。

  6. 缓存机制:内置了两级缓存机制(一级缓存是 Session 级别的,二级缓存是全局的),可以提高数据访问速度,减少数据库负载。

  7. 插件支持:MyBatis 提供了丰富的插件接口,允许开发者自定义拦截器来修改或增强其行为,比如添加日志记录、性能监控等。

DefaultSqlSessionFactory vs SqlSessionManager

在MyBatis中,DefaultSqlSessionFactorySqlSessionManager是两个重要的类,它们的定位和作用有所不同。以下是它们的详细解释及区别:

DefaultSqlSessionFactory

定位和作用
  • 定位DefaultSqlSessionFactory是MyBatis中用于创建SqlSession实例的默认工厂实现。
  • 作用:负责根据配置文件(如mybatis-config.xml)创建和配置SqlSession,并提供获取SqlSession实例的方法。
  • 实现:通常通过SqlSessionFactoryBuilder创建DefaultSqlSessionFactory实例。
主要功能
  • 创建SqlSession:通过调用openSession()方法来创建新的SqlSession实例。
  • 配置管理:读取和解析MyBatis配置文件,管理数据库连接、事务、映射器等。
示例代码
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

SqlSessionManager

定位和作用
  • 定位SqlSessionManager是MyBatis中提供的一种方便管理SqlSession生命周期的工具类,支持线程安全的操作。
  • 作用:简化SqlSession的管理,支持自动提交、自动关闭以及与当前线程绑定的SqlSession实例。
  • 实现:可以将SqlSessionManager视为对DefaultSqlSessionFactory的一种增强,实现了SqlSessionFactorySqlSession接口。
主要功能
  • 线程安全:确保同一线程中使用相同的SqlSession实例,避免线程不安全问题。
  • 自动管理:提供自动提交和自动关闭SqlSession的功能,减少手动管理的复杂性。
  • 简化事务管理:提供便捷的方法进行事务管理,如自动提交和回滚。
示例代码
SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(inputStream);
sqlSessionManager.startManagedSession();
try {
    UserMapper mapper = sqlSessionManager.getMapper(UserMapper.class);
    User user = mapper.selectUser(1);
    sqlSessionManager.commit();
} finally {
    sqlSessionManager.close();
}

区别

  • 创建方式

    • DefaultSqlSessionFactory通常通过SqlSessionFactoryBuilder创建。
    • SqlSessionManager通过静态方法newInstance()创建。
  • 线程管理

    • DefaultSqlSessionFactory创建的SqlSession实例需要手动管理,不提供线程安全保证。
    • SqlSessionManager在同一线程中共享SqlSession实例,确保线程安全。
  • 事务管理

    • DefaultSqlSessionFactory需要手动管理事务,手动提交和回滚。
    • SqlSessionManager提供自动提交和回滚功能,简化事务管理。
  • 使用场景

    • DefaultSqlSessionFactory适用于需要精细控制SqlSession生命周期的场景。
    • SqlSessionManager适用于需要简化SqlSession管理和保证线程安全的场景。

总结来说,DefaultSqlSessionFactory是一个基础的SqlSession工厂,提供基本的SqlSession创建功能,而SqlSessionManager在其基础上增强了线程安全和自动管理功能,适用于简化SqlSession管理的应用场景。

Configuration

StrictMap

MyBatis中的StrictMap是一个特殊的内部数据结构,用于增强MyBatis配置和运行时的安全性和可调试性。以下是StrictMap的特点以及它解决的问题:

StrictMap的特点

  1. 严格检查StrictMap在插入和访问元素时会进行严格检查,确保键的唯一性和存在性。
  2. 增强错误信息:当访问不存在的键时,StrictMap会抛出详细的异常信息,帮助开发者快速定位问题。
  3. 类型安全StrictMap可以确保存储和检索的对象类型一致,避免类型转换异常。

解决的问题

  1. 防止重复键:在MyBatis配置中(如Mapper XML配置),避免因重复定义同一个键(如SQL语句ID、Mapper接口等)导致的问题。StrictMap会在添加重复键时抛出异常,提醒开发者修正。
  2. 防止未定义的键:在运行时访问未定义的键时,StrictMap会抛出异常,防止因配置错误或代码错误导致的空指针异常或其他运行时错误。
  3. 增强调试能力:提供详细的异常信息,有助于快速定位和修复配置或代码中的问题。

示例
假设在MyBatis的Mapper XML文件中,定义了两个相同的SQL语句ID:

<mapper namespace="com.example.mapper.UserMapper">
  <select id="selectUser" resultType="User">
    SELECT * FROM users WHERE id = #{id}
  </select>
  
  <!-- 重复定义相同的ID -->
  <select id="selectUser" resultType="User">
    SELECT * FROM users WHERE name = #{name}
  </select>
</mapper>

在这种情况下,StrictMap会抛出一个异常,指出存在重复的键selectUser,从而帮助开发者及时发现并修正配置错误。

使用场景

  • MyBatis配置加载:在加载和解析MyBatis配置文件时,使用StrictMap确保配置的正确性。
  • 运行时映射管理:在运行时管理Mapper接口和SQL语句映射时,使用StrictMap确保访问的安全性和一致性。

总结
StrictMap的主要特点和作用如下:

  • 严格检查键的唯一性和存在性,防止重复定义和访问未定义的键。
  • 提供详细的异常信息,增强调试能力,帮助快速定位和修复问题。
  • 确保类型安全,避免类型转换异常。

SqlSessionFactory

SqlSessionFactory 是 MyBatis 框架中的一个核心组件,它扮演着工厂的角色,负责创建 SqlSession 对象。

如何创建 SqlSessionFactory

创建 SqlSessionFactory 主要有以下几个步骤:

  1. 准备配置信息:首先,需要准备 MyBatis 的配置信息,这些信息通常定义在 mybatis-config.xml 文件中,包括数据库连接信息(如 URL、用户名、密码)、事务管理设置、映射文件位置等。此外,也可以通过 Java 代码的方式来动态构建这些配置信息。

  2. 构建 SqlSessionFactoryBuilder:接下来,使用 SqlSessionFactoryBuilder 类来创建 SqlSessionFactorySqlSessionFactoryBuilder 提供了多个 build 方法,可以从 XML 配置文件、Reader 对象或者直接从配置对象来构建 SqlSessionFactory

  3. 使用配置创建 SqlSessionFactory:通过 SqlSessionFactoryBuilderbuild 方法,传入之前准备好的配置信息或资源,即可创建出 SqlSessionFactory 实例。例如,如果配置信息在 XML 文件中,可以像这样创建:

    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
  4. 配置 MyBatis-Spring 集成:如果在 Spring 环境中使用 MyBatis,可以通过配置 SqlSessionFactoryBean 来自动创建和管理 SqlSessionFactory,这种方式更加符合 Spring 的管理方式,并能更好地与 Spring 的其他特性(如事务管理)集成。

一旦 SqlSessionFactory 创建成功,就可以从中获取 SqlSession 对象,进而执行 SQL 操作。通常,一个应用程序只需要一个 SqlSessionFactory 实例,并在整个应用生命周期中重复使用它来创建 SqlSession

SqlSession

SqlSession是MyBatis中的一个核心接口,代表了与数据库的一次会话。它主要用于执行SQL命令、管理事务以及与数据库进行交互。以下是对SqlSession的详细解释及其作用:

SqlSession是什么

SqlSession是MyBatis提供的一个接口,用于封装和管理与数据库交互的所有操作。它类似于JDBC中的Connection,但提供了更高级别的抽象,简化了与数据库的交互。

SqlSession的作用

  1. 执行SQL命令SqlSession提供了多种方法来执行SQL查询、插入、更新和删除操作。这些方法包括selectOne, selectList, insert, update, delete等。

  2. 事务管理SqlSession支持显式的事务管理。可以通过commit方法提交事务,通过rollback方法回滚事务。这使得MyBatis在处理事务时更加灵活和方便。

  3. Mapper接口映射SqlSession允许通过Mapper接口执行SQL操作。Mapper接口中的方法通过SqlSession执行相应的SQL语句,使得代码更具可读性和可维护性。

  4. 资源管理SqlSession管理数据库连接和其他资源。在操作完成后,必须显式地关闭SqlSession以释放资源,避免资源泄漏。

SqlSession的常用方法

  • selectOne:查询单条记录。
  • selectList:查询多条记录。
  • insert:插入记录。
  • update:更新记录。
  • delete:删除记录。
  • commit:提交事务。
  • rollback:回滚事务。
  • close:关闭SqlSession,释放资源。

示例代码

下面是一个使用SqlSession进行数据库操作的简单示例:

// 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 获取SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
    // 获取Mapper接口的实现
    UserMapper mapper = session.getMapper(UserMapper.class);

    // 执行查询
    User user = mapper.selectUser(1);
    System.out.println(user);

    // 执行插入
    User newUser = new User();
    newUser.setName("John");
    newUser.setEmail("[email protected]");
    mapper.insertUser(newUser);

    // 提交事务
    session.commit();
} catch (Exception e) {
    e.printStackTrace();
    // 回滚事务
    session.rollback();
}

总结

  • SqlSession是MyBatis与数据库交互的核心接口,封装了所有的数据库操作。
  • SqlSession提供了执行SQL命令、管理事务、获取Mapper接口实现和管理资源的功能
  • 在使用SqlSession时,必须显式地关闭它以释放资源,通常使用try-with-resources语句来确保这一点。

Mapper

MyBatis的Mapper接口是MyBatis框架中用来与数据库交互的重要组件之一。它将Java方法与SQL语句映射起来,使得开发者可以通过调用Java方法来执行SQL操作。以下是MyBatis的Mapper接口及其作用的详细解释:

Mapper接口简介

Mapper接口是MyBatis的核心功能之一,通过Java接口与SQL映射文件(或注解)结合,实现对数据库的操作。Mapper接口可以直接映射SQL语句,避免了直接在代码中编写SQL,提升了代码的可维护性和可读性。

Mapper接口的作用

  1. 简化SQL操作:通过Mapper接口,开发者可以使用Java方法直接执行SQL操作,而不需要手动编写SQL语句。
  2. 类型安全:Mapper接口方法的参数和返回类型都可以通过Java类型安全地定义,避免了类型转换错误。
  3. 代码可读性:使用Mapper接口,数据库操作被抽象为接口方法,代码更加简洁和易读。
  4. 自动映射:MyBatis可以自动将查询结果映射到Java对象,减少了手动处理结果集的代码。
  5. 配置管理:SQL语句和数据库操作被集中在Mapper XML文件或注解中,便于管理和维护。

示例

定义Mapper接口
public interface UserMapper {
    User selectUser(int id);
    void insertUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}
配置Mapper XML文件
<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectUser" resultType="com.example.domain.User">
        SELECT * 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>
使用Mapper接口
public class MyBatisExample {
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        
        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            
            // 查询用户
            User user = mapper.selectUser(1);
            System.out.println(user);
            
            // 插入用户
            User newUser = new User();
            newUser.setName("John");
            newUser.setEmail("[email protected]");
            mapper.insertUser(newUser);
            session.commit();
            
            // 更新用户
            user.setName("Jane");
            user.setEmail("[email protected]");
            mapper.updateUser(user);
            session.commit();
            
            // 删除用户
            mapper.deleteUser(1);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用注解代替XML

Mapper接口也可以使用注解来定义SQL语句,减少对XML配置文件的依赖:

public interface UserMapper {
    @Select("SELECT * 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);
}

总结

Mapper接口是MyBatis中重要的组成部分,主要作用如下:

  1. 简化数据库操作:通过接口方法调用,避免手动编写SQL语句。
  2. 提升代码可读性和可维护性:通过接口和注解(或XML)分离SQL和Java代码。
  3. 类型安全和自动映射:自动将查询结果映射到Java对象,避免类型转换错误。

配置

mybatis-config常见配置项

在Java高级开发面试中,了解MyBatis的mybatis-config.xml配置文件是非常重要的,因为这通常反映了你对框架底层实现的理解程度。以下是一些常见的配置项及其用途:

  1. environments

    • transactionManager:配置事务管理器,通常设置为JDBCMANAGED
    • dataSource:配置数据源,可以是POOLED(连接池)、UNPOOLED(每次请求创建新连接)、JNDI(通过JNDI获取数据源)。
  2. mappers

    • 指定Mapper接口或XML映射文件的位置,可以使用package属性扫描包内所有的Mapper接口,或者直接列出XML映射文件的路径。
  3. settings

    • 这里可以配置MyBatis的行为,例如:
      • cacheEnabled:是否启用缓存。
        • 作用:控制MyBatis是否使用一级缓存或二级缓存。
        • 影响:如果启用缓存,MyBatis会在执行相同SQL查询时尝试从缓存中获取结果,而不是每次都查询数据库,这可以显著提高读取密集型应用的性能。但要注意,如果数据频繁更新,缓存可能需要被清理以保持数据一致性。
      • lazyLoadingEnabled:是否启用延迟加载。
        • 作用:控制关联对象是否延迟加载。
        • 影响:如果启用延迟加载,那么在加载一个对象时,其关联的对象(如通过一对多或多对一关系)不会立即加载,而是在真正需要的时候才加载。这样可以减少初始查询的复杂性和数据量,提高应用的响应速度。
      • multipleResultSetsEnabled:是否允许单次执行返回多结果集。
        • 作用:允许执行的SQL语句返回多个结果集。
        • 影响:在某些数据库操作中,可能需要返回多个结果集。例如,在执行存储过程时。如果禁用此选项,MyBatis将无法处理返回的多个结果集,可能导致查询失败。
      • useGeneratedKeys:是否使用JDBC的getGeneratedKeys()方法来返回主键。
        • 作用:控制MyBatis是否使用JDBC的getGeneratedKeys()方法来返回自动生成的主键。
        • 影响:如果启用了这个设置,那么在插入记录后,MyBatis可以自动检索生成的主键,并将其赋值给Java对象的相应属性,这可以简化主键的管理和使用。
      • autoMappingBehavior:自动映射行为,如PARTIAL或FULL。
      • defaultExecutorType:执行器类型,如SIMPLE、REUSE或BATCH。
  4. typeAliases

    • 定义类型别名,简化Mapper中的类型名称,可以使用typeAlias标签单独定义,或者使用typeAliases标签并指定一个包含实体类的包名。
  5. typeHandlers

    • 自定义类型处理器,用于处理Java类型和数据库类型之间的转换。
  6. plugins

    • 插件可以拦截执行过程,用于修改SQL语句、参数或结果,例如分页插件。
  7. objectFactory

    • 配置对象工厂,控制MyBatis如何创建Java对象实例。
  8. objectWrapperFactory

    • 配置对象包装工厂,用于决定对象的封装方式。
  9. reflectionFactory

    • 控制反射机制的实现方式。
  10. properties

    • 可以在配置文件中引用外部的属性文件,例如数据库连接信息。
  11. VFS

    • 虚拟文件系统配置,用于指定MyBatis如何访问映射文件。
  12. databaseIdProvider

    • 数据库ID提供者,用于数据库驱动的识别和特定驱动的SQL语法调整。

面试时,可能会询问你如何配置这些选项,以及它们的具体作用和可能的影响。

dataSource

数据源配置是任何基于数据库的应用程序的重要组成部分,它涉及到如何设置和管理应用程序与数据库之间的连接。数据源通常用于创建和管理一个数据库连接池,以优化数据库访问的性能和资源利用。以下是数据源配置的一些关键方面:

1. 数据源概念

数据源(DataSource)是JDBC API的一部分,它提供了一种创建和管理数据库连接的方式。数据源的主要优势在于它可以重用和管理数据库连接,避免了每次访问数据库时创建和销毁连接的开销,这在高并发环境下尤其重要。

2. 数据源类型

数据源可以分为多种类型,每种类型都有其特定的用途和优点:

  • DriverManagerDataSource: Spring框架自带的一种简单数据源,直接使用JDBC的DriverManager来创建连接。不推荐在生产环境中使用,因为它不支持连接池。

  • DBCP: Apache Commons DBCP是一个开源的数据库连接池实现,它可以复用数据库连接,减少创建和销毁连接的开销。

  • C3P0: 另一个流行的开源数据库连接池实现,提供了更多的特性和配置选项,适用于各种应用场景。

  • HikariCP: 一个高性能的JDBC连接池,以其低延迟和高吞吐量著称,是现代Web应用的首选。

  • Tomcat JNDI DataSource: 如果你的应用运行在Tomcat服务器上,可以使用内置的JNDI数据源,这可以简化配置并利用服务器级别的连接管理。

3. 数据源配置

数据源配置通常涉及以下几个步骤:

  • 引入依赖: 首先,你需要在项目的构建配置文件中添加相应的数据源库和数据库驱动的依赖。

  • 配置数据源: 你可以在配置文件(如application.properties或application.yml)中定义数据源的属性,包括数据库URL、用户名、密码、最大连接数、最小连接数等。

  • 创建数据源: 在代码中创建数据源实例,并设置上述属性。

  • 使用数据源: 应用程序通过数据源获取数据库连接,执行数据库操作后,连接会被归还到连接池中,供后续使用。

4. 示例配置

以下是使用Spring Boot和HikariCP数据源的一个示例配置:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database
    username: your_username
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      idle-timeout: 30000

在这个配置中,spring.datasource.*属性用于配置HikariCP数据源,包括数据库的URL、用户名、密码、驱动类以及连接池的大小和超时设置。

5. 动态数据源

在某些情况下,你可能需要在应用程序中配置多个数据源,例如为了分库分表或读写分离。这可以通过使用Spring AOP和自定义数据源路由逻辑来实现。在运行时,根据业务需求动态选择适当的数据源。

Mapper

Mapper文件的基本结构通常包括以下组成部分:

  1. 根元素 <mapper>

    • 这是Mapper文件的根标签,它需要一个namespace属性,该属性的值通常是Mapper接口的全限定类名。这个命名空间用来唯一标识Mapper中的各个映射语句。
  2. SQL语句定义

    • Mapper文件中可以包含各种SQL语句定义,包括<select>, <insert>, <update>, 和 <delete>等。这些标签定义了具体的SQL语句以及返回类型或参数类型。
  3. 参数映射

    • 在SQL语句中,你可以使用#{}占位符来引用Java方法的参数或对象的属性。MyBatis会自动进行参数绑定。
  4. 结果映射

    • <resultMap>元素用于描述如何将结果集中的列映射到Java对象的属性上。这在处理复杂的一对多或多对一关系时非常有用。
  5. 动态SQL

    • MyBatis支持动态SQL,允许你在SQL语句中使用条件语句(如<if><choose>)、循环语句(如<foreach>)等,使得SQL语句更加灵活。
  6. 缓存配置

    • <cache>元素可以配置Mapper级别的缓存,用于提高读取性能。
  7. 其他元素

    • <sql>元素用于定义可重用的SQL片段,可以包含在其他语句中。
    • <include>元素用于包含另一个Mapper文件的内容,便于代码重用。
    • <discriminator>元素用于多态结果集映射,当查询结果包含类型区分字段时使用。

以下是一个简单的Mapper文件示例:

<mapper namespace="com.example.mapper.UserMapper">
  <!-- 定义一个可重用的SQL片段 -->
  <sql id="commonColumns">id, name, age, email</sql>

  <!-- 查询所有用户 -->
  <select id="selectAllUsers" resultType="com.example.domain.User">
    select
      ${commonColumns}
    from user
  </select>

  <!-- 根据ID查询用户 -->
  <select id="getUserById" parameterType="int" resultType="com.example.domain.User">
    select
      ${commonColumns}
    from user
    where id = #{id}
  </select>

  <!-- 添加新用户 -->
  <insert id="addUser" parameterType="com.example.domain.User">
    insert into user (name, age, email)
    values (#{name}, #{age}, #{email})
  </insert>

  <!-- 更新现有用户 -->
  <update id="updateUser" parameterType="com.example.domain.User">
    update user
    set name = #{name}, age = #{age}, email = #{email}
    where id = #{id}
  </update>

  <!-- 删除用户 -->
  <delete id="deleteUser" parameterType="int">
    delete from user
    where id = #{id}
  </delete>
</mapper>

在这个例子中,<mapper>元素包含了基本的CRUD操作,每个操作都有一个唯一的ID,这个ID用来在Mapper接口中引用。例如,<select id="selectAllUsers">将在Mapper接口中表现为List<User> selectAllUsers();方法。

Mapper 参数映射和结果映射

参数映射

基本参数映射

在MyBatis中,最简单的参数映射是使用#{}语法来引用方法参数或对象属性。例如,在Mapper接口中定义如下方法:

int updateUserById(User user);

对应的XML映射文件中可以这样写SQL语句:

<update id="updateUserById" parameterType="com.example.domain.User">
  UPDATE user SET name=#{name}, age=#{age} WHERE id=#{id}
</update>

这里,#{}内的变量名需要与传递给方法的参数或对象的属性名一致。

复杂参数映射

对于复杂的参数对象,MyBatis提供了更高级的映射机制。例如,如果User对象中包含嵌套的对象,如Address,可以这样映射:

<update id="updateUserWithAddress" parameterType="com.example.domain.User">
  UPDATE user SET name=#{name}, address.city=#{address.city}, address.state=#{address.state} WHERE id=#{id}
</update>

此外,还可以使用@Param注解为方法参数指定别名,这对于多个同名参数或复杂参数场景非常有用:

int updateUserById(@Param("id") int id, @Param("name") String name);
<update id="updateUserById">
  UPDATE user SET name=#{name} WHERE id=#{id}
</update>

结果映射

简单结果映射

最基础的结果映射是将查询结果的列直接映射到Java对象的属性上。例如:

<select id="selectUserById" resultType="com.example.domain.User">
  SELECT * FROM user WHERE id=#{id}
</select>

这里,resultType属性指定了结果映射的目标类型,MyBatis会尝试将列名与Java对象的属性名进行匹配。

复杂结果映射

对于复杂的结果集,如关联查询返回的结果,使用<resultMap>元素可以更精细地控制映射规则。例如,假设有一个一对多的关系,UserOrder,可以这样定义映射:

<resultMap id="UserWithOrdersMap" type="com.example.domain.User">
  <id property="id" column="user_id"/>
  <result property="name" column="name"/>
  
  <collection property="orders" ofType="com.example.domain.Order">
    <id property="id" column="order_id"/>
    <result property="amount" column="amount"/>
  </collection>
</resultMap>

<select id="selectUserWithOrders" resultMap="UserWithOrdersMap">
  SELECT u.*, o.id as order_id, o.amount 
  FROM user u LEFT JOIN `order` o ON u.id = o.user_id
  WHERE u.id = #{userId}
</select>

在上面的例子中,<resultMap>元素定义了一个映射规则,其中<id><result>用于映射User对象,而<collection>则用于处理Order集合的映射。

动态SQL和结果映射

在使用动态SQL时,结果映射也需要相应调整。例如,使用<if>条件语句时,MyBatis会根据条件动态生成列名,这时需要确保resultMap中定义的列名与实际生成的列名相匹配。

性能优化

在处理大数据量时,结果映射的性能也非常重要。可以考虑使用懒加载(lazy loading)和二级缓存(second-level cache)来优化性能。例如,通过在<resultMap>中为集合属性添加fetchType="lazy"属性,可以实现懒加载。

标签:Mapper,Java,映射,SqlSession,30k,SQL,MyBatis,id
From: https://blog.csdn.net/weixin_41379244/article/details/140112650

相关文章

  • MyBatis-利用切面实现公有字段自动填充(非MyBatisPlus方式)
    需求:在MyBatis框架中,如何对createBy,createTime,updateBy等这些公有字段实现自动填充呢?网上搜了很多,实现的方案全是采用集成MyBatisPlus,利用其封装好的方法来实现的。。。。。数据准备:1、准备一张数据库表CREATETABLE`user`(`id`varchar(36)NOTNULL,`username`......
  • Java语言编程基础——总结
    目录Java基本语法语句和表达式注释关键字标识符Java基本数据类型整数类型:浮点类型:字符类型:布尔类型:Java的运算符        算术运算符:        赋值运算符:        比较运算符:        逻辑运算符:        位运算符:   ......
  • 通过更改java环境变量修改java版本不生效问题
    目录问题复现解决方法问题复现本地生产环境时java8,但是新项目需要java11.于是我下载了jdk11,并修改了环境变量。之后使用java-version,发现java版本还是8,并没没有更改成11解决方法参考文章输入wherejava将这个路径下的java.exe删除就好了。......
  • Java(Spring Boot)编程思想学习进阶书籍
    1、SpringBoot编程思想(核心篇)该书是《SpringBoot编程思想》的核心篇,开篇总览SpringBoot核心特性,接着讨论自动装配(Auto-Configuration)与SpringApplication。《SpringBoot编程思想(核心篇)》的讨论以SpringBoot为中心,议题发散至Spring技术栈、JSR及Java。希望透过全局的视角,......
  • Java Web---Filter(过滤器)
            Java过滤器是一个用来处理HTTP请求和响应的组件,它可以拦截客户端发送给服务器的请求,并在请求到达目标资源之前对请求进行修改或者对请求进行一些预处理操作。应用场景:用户权限控制:通过过滤器可以拦截用户请求,检查用户是否具有访问某个资源的权限,然后根据权......
  • 【秋招突围】2024届秋招笔试-科大讯飞笔试题-03-三语言题解(Java/Cpp/Python)
    ......
  • 已解决java.security.acl.NotOwnerException:在ACL中尝试执行非所有者的操作的正确解决
    已解决java.security.acl.NotOwnerException:在ACL中尝试执行非所有者的操作的正确解决方法,亲测有效!!!目录问题分析出现问题的场景用户类和ACL初始化报错原因解决思路解决方法1.验证所有者身份示例代码2.正确设置所有者示例代码完整示例代码主类和ACL管理代码总......
  • 已解决java.rmi.NotBoundException:RMI中没有绑定的对象的正确解决方法,亲测有效!!!
    已解决java.rmi.NotBoundException:RMI中没有绑定的对象的正确解决方法,亲测有效!!!目录问题分析出现问题的场景服务器端代码客户端代码报错原因解决思路解决方法1.绑定远程对象2.检查查找名称3.验证RMI注册表启动RMI注册表完整示例代码服务器端代码客户端代码......
  • Java随笔2
    3.构造器作用1:搭配new关键字,创建类的对象作用2:在创建对象的同时,可以给对象的相关属性赋值使用说明>构造器声明的格式:权限修饰符类名(形参列表){}>创建类以后,在没有显示提供任何构造器的情况下,系统会默认提供一个空参的构造器,且构造器的权限与类声明的权限相同。>一旦类中显示声......
  • 基于Java的小区家政服务预约平台
    作者介绍:✌全网粉丝10W+本平台特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于毕业项目实战✌一、作品包含源码+数据库+设计文档万字LW+PPT+全套环境和工具资源+部署教程二、项目技术前端......