基础知识
架构图
MyBatis的基本架构图,展示MyBatis核心组件及其相互关系:
解释
- 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 的核心功能主要包括以下几个方面:
-
SQL 映射:允许开发者在 XML 文件或 Java 注解中编写 SQL 语句,并将这些 SQL 与 Java 方法绑定。这为 SQL 提供了清晰的组织结构和可重用性,同时保持了 SQL 的灵活性。
-
参数映射:自动将 Java 方法的参数转换为 SQL 语句中的参数。MyBatis 支持多种参数类型和复杂的映射规则,使得参数传递变得简单且灵活。
-
结果映射:将查询结果自动映射到 Java 对象(POJOs,即 Plain Old Java Objects),无需手动处理结果集。MyBatis 支持复杂的映射关系,包括一对一、一对多和多对多关联映射。
-
动态 SQL:支持在 SQL 语句中嵌入条件逻辑,如
if
、choose
、when
、otherwise
、where
、set
等标签,使得 SQL 语句可以根据传入参数动态改变,提高了 SQL 的复用性和灵活性。 -
事务管理:MyBatis 提供了对事务的简单管理,可以通过
SqlSession
来提交或回滚事务。 -
缓存机制:内置了两级缓存机制(一级缓存是 Session 级别的,二级缓存是全局的),可以提高数据访问速度,减少数据库负载。
-
插件支持:MyBatis 提供了丰富的插件接口,允许开发者自定义拦截器来修改或增强其行为,比如添加日志记录、性能监控等。
DefaultSqlSessionFactory vs SqlSessionManager
在MyBatis中,DefaultSqlSessionFactory
和SqlSessionManager
是两个重要的类,它们的定位和作用有所不同。以下是它们的详细解释及区别:
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
的一种增强,实现了SqlSessionFactory
和SqlSession
接口。
主要功能
- 线程安全:确保同一线程中使用相同的
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
的特点
- 严格检查:
StrictMap
在插入和访问元素时会进行严格检查,确保键的唯一性和存在性。 - 增强错误信息:当访问不存在的键时,
StrictMap
会抛出详细的异常信息,帮助开发者快速定位问题。 - 类型安全:
StrictMap
可以确保存储和检索的对象类型一致,避免类型转换异常。
解决的问题
- 防止重复键:在MyBatis配置中(如Mapper XML配置),避免因重复定义同一个键(如SQL语句ID、Mapper接口等)导致的问题。
StrictMap
会在添加重复键时抛出异常,提醒开发者修正。 - 防止未定义的键:在运行时访问未定义的键时,
StrictMap
会抛出异常,防止因配置错误或代码错误导致的空指针异常或其他运行时错误。 - 增强调试能力:提供详细的异常信息,有助于快速定位和修复配置或代码中的问题。
示例
假设在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
主要有以下几个步骤:
-
准备配置信息:首先,需要准备 MyBatis 的配置信息,这些信息通常定义在
mybatis-config.xml
文件中,包括数据库连接信息(如 URL、用户名、密码)、事务管理设置、映射文件位置等。此外,也可以通过 Java 代码的方式来动态构建这些配置信息。 -
构建
SqlSessionFactoryBuilder
:接下来,使用SqlSessionFactoryBuilder
类来创建SqlSessionFactory
。SqlSessionFactoryBuilder
提供了多个build
方法,可以从 XML 配置文件、Reader 对象或者直接从配置对象来构建SqlSessionFactory
。 -
使用配置创建
SqlSessionFactory
:通过SqlSessionFactoryBuilder
的build
方法,传入之前准备好的配置信息或资源,即可创建出SqlSessionFactory
实例。例如,如果配置信息在 XML 文件中,可以像这样创建:String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
-
配置 MyBatis-Spring 集成:如果在 Spring 环境中使用 MyBatis,可以通过配置
SqlSessionFactoryBean
来自动创建和管理SqlSessionFactory
,这种方式更加符合 Spring 的管理方式,并能更好地与 Spring 的其他特性(如事务管理)集成。
一旦 SqlSessionFactory
创建成功,就可以从中获取 SqlSession
对象,进而执行 SQL 操作。通常,一个应用程序只需要一个 SqlSessionFactory
实例,并在整个应用生命周期中重复使用它来创建 SqlSession
。
SqlSession
SqlSession
是MyBatis中的一个核心接口,代表了与数据库的一次会话。它主要用于执行SQL命令、管理事务以及与数据库进行交互。以下是对SqlSession
的详细解释及其作用:
SqlSession
是什么
SqlSession
是MyBatis提供的一个接口,用于封装和管理与数据库交互的所有操作。它类似于JDBC中的Connection
,但提供了更高级别的抽象,简化了与数据库的交互。
SqlSession
的作用
-
执行SQL命令:
SqlSession
提供了多种方法来执行SQL查询、插入、更新和删除操作。这些方法包括selectOne
,selectList
,insert
,update
,delete
等。 -
事务管理:
SqlSession
支持显式的事务管理。可以通过commit
方法提交事务,通过rollback
方法回滚事务。这使得MyBatis在处理事务时更加灵活和方便。 -
Mapper接口映射:
SqlSession
允许通过Mapper接口执行SQL操作。Mapper接口中的方法通过SqlSession
执行相应的SQL语句,使得代码更具可读性和可维护性。 -
资源管理:
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接口的作用
- 简化SQL操作:通过Mapper接口,开发者可以使用Java方法直接执行SQL操作,而不需要手动编写SQL语句。
- 类型安全:Mapper接口方法的参数和返回类型都可以通过Java类型安全地定义,避免了类型转换错误。
- 代码可读性:使用Mapper接口,数据库操作被抽象为接口方法,代码更加简洁和易读。
- 自动映射:MyBatis可以自动将查询结果映射到Java对象,减少了手动处理结果集的代码。
- 配置管理: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中重要的组成部分,主要作用如下:
- 简化数据库操作:通过接口方法调用,避免手动编写SQL语句。
- 提升代码可读性和可维护性:通过接口和注解(或XML)分离SQL和Java代码。
- 类型安全和自动映射:自动将查询结果映射到Java对象,避免类型转换错误。
配置
mybatis-config常见配置项
在Java高级开发面试中,了解MyBatis的mybatis-config.xml
配置文件是非常重要的,因为这通常反映了你对框架底层实现的理解程度。以下是一些常见的配置项及其用途:
-
environments
transactionManager
:配置事务管理器,通常设置为JDBC
或MANAGED
。dataSource
:配置数据源,可以是POOLED
(连接池)、UNPOOLED
(每次请求创建新连接)、JNDI
(通过JNDI获取数据源)。
-
mappers
- 指定Mapper接口或XML映射文件的位置,可以使用
package
属性扫描包内所有的Mapper接口,或者直接列出XML映射文件的路径。
- 指定Mapper接口或XML映射文件的位置,可以使用
-
settings
- 这里可以配置MyBatis的行为,例如:
cacheEnabled
:是否启用缓存。- 作用:控制MyBatis是否使用一级缓存或二级缓存。
- 影响:如果启用缓存,MyBatis会在执行相同SQL查询时尝试从缓存中获取结果,而不是每次都查询数据库,这可以显著提高读取密集型应用的性能。但要注意,如果数据频繁更新,缓存可能需要被清理以保持数据一致性。
lazyLoadingEnabled
:是否启用延迟加载。- 作用:控制关联对象是否延迟加载。
- 影响:如果启用延迟加载,那么在加载一个对象时,其关联的对象(如通过一对多或多对一关系)不会立即加载,而是在真正需要的时候才加载。这样可以减少初始查询的复杂性和数据量,提高应用的响应速度。
multipleResultSetsEnabled
:是否允许单次执行返回多结果集。- 作用:允许执行的SQL语句返回多个结果集。
- 影响:在某些数据库操作中,可能需要返回多个结果集。例如,在执行存储过程时。如果禁用此选项,MyBatis将无法处理返回的多个结果集,可能导致查询失败。
useGeneratedKeys
:是否使用JDBC的getGeneratedKeys()方法来返回主键。- 作用:控制MyBatis是否使用JDBC的
getGeneratedKeys()
方法来返回自动生成的主键。 - 影响:如果启用了这个设置,那么在插入记录后,MyBatis可以自动检索生成的主键,并将其赋值给Java对象的相应属性,这可以简化主键的管理和使用。
- 作用:控制MyBatis是否使用JDBC的
autoMappingBehavior
:自动映射行为,如PARTIAL或FULL。defaultExecutorType
:执行器类型,如SIMPLE、REUSE或BATCH。
- 这里可以配置MyBatis的行为,例如:
-
typeAliases
- 定义类型别名,简化Mapper中的类型名称,可以使用
typeAlias
标签单独定义,或者使用typeAliases
标签并指定一个包含实体类的包名。
- 定义类型别名,简化Mapper中的类型名称,可以使用
-
typeHandlers
- 自定义类型处理器,用于处理Java类型和数据库类型之间的转换。
-
plugins
- 插件可以拦截执行过程,用于修改SQL语句、参数或结果,例如分页插件。
-
objectFactory
- 配置对象工厂,控制MyBatis如何创建Java对象实例。
-
objectWrapperFactory
- 配置对象包装工厂,用于决定对象的封装方式。
-
reflectionFactory
- 控制反射机制的实现方式。
-
properties
- 可以在配置文件中引用外部的属性文件,例如数据库连接信息。
-
VFS
- 虚拟文件系统配置,用于指定MyBatis如何访问映射文件。
-
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文件的基本结构通常包括以下组成部分:
-
根元素
<mapper>
- 这是Mapper文件的根标签,它需要一个
namespace
属性,该属性的值通常是Mapper接口的全限定类名。这个命名空间用来唯一标识Mapper中的各个映射语句。
- 这是Mapper文件的根标签,它需要一个
-
SQL语句定义
- Mapper文件中可以包含各种SQL语句定义,包括
<select>
,<insert>
,<update>
, 和<delete>
等。这些标签定义了具体的SQL语句以及返回类型或参数类型。
- Mapper文件中可以包含各种SQL语句定义,包括
-
参数映射
- 在SQL语句中,你可以使用
#{}
占位符来引用Java方法的参数或对象的属性。MyBatis会自动进行参数绑定。
- 在SQL语句中,你可以使用
-
结果映射
<resultMap>
元素用于描述如何将结果集中的列映射到Java对象的属性上。这在处理复杂的一对多或多对一关系时非常有用。
-
动态SQL
- MyBatis支持动态SQL,允许你在SQL语句中使用条件语句(如
<if>
、<choose>
)、循环语句(如<foreach>
)等,使得SQL语句更加灵活。
- MyBatis支持动态SQL,允许你在SQL语句中使用条件语句(如
-
缓存配置
<cache>
元素可以配置Mapper级别的缓存,用于提高读取性能。
-
其他元素
<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>
元素可以更精细地控制映射规则。例如,假设有一个一对多的关系,User
和Order
,可以这样定义映射:
<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"
属性,可以实现懒加载。