目录
1. 概述
1.1 MyBatis简介
1.2 MyBatis历史演变
1.3 MyBatis的优点和局限性
1.3.1 优点
1.3.2 局限性
2. 入门指南
2.1 安装和配置MyBatis
2.1.1 MyBatis的安装
2.1.2 数据库连接池的选择
2.1.3 MyBatis配置方式
2.1.3.1 基于xml配置文件配置
2.1.3.2 基于yaml配置文件配置
2.1.3.3 基于注解配置文配置
2.2 如何使用MyBatis
2.2.1 基础CRUD操作
2.2.1.1 映射文件的编写
2.2.1.2 Java代码的编写
2.2.2 动态SQL语句的编写
2.2.2.1 if元素
2.2.2.2 where元素
2.2.2.3 foreach元素
2.2.3 插入操作
2.2.3.1 手动指定ID
2.2.3.2 数据库自动生成ID
2.2.4 删除操作
2.2.5 更新操作
2.2.6 多表关联查询
2.2.6.1 一对一关联查询
2.2.6.2 一对多关联查询
2.2.7 一些高级功能
2.2.7.1 缓存机制
2.2.7.2 分页插件
3. MyBatis的高级应用
3.1 MyBatis整合Spring
3.1.1 原理
3.1.2 配置方法
3.2 MyBatis Generator——自动化生成MyBatis代码
3.2.1 基础原理
3.2.2 文件生成策略
3.2.3 使用方式
3.3 代码生成器:MyBatis Plus
3.3.1 MyBatis Plus简介
3.3.2 MyBatis Plus的优点和局限性
3.3.3 MyBatis Plus的使用
3.3.3.1 引入MyBatis Plus
3.3.3.2 自动生成代码
3.3.3.3 Lambda查询
3.3.3.4 分页查询
3.3.3.5 多租户支持
4. 最佳实践
4.1 掌握MyBatis数据表设计
4.1.1 表设计规范
4.1.2 表关系设计
4.2 映射文件编写的要点
4.2.1 SQL语句编写
4.2.2 映射规则编写
4.3 编写高效的SQL语句
4.3.1 避免使用子查询
4.3.2 避免使用%前缀模糊查询
5. 总结
5.1 MyBatis的未来
5.2 MyBatis的注意事项以及常见问题
MyBatis是一个基于Java语言的持久层框架,它通过XML描述符或注解将对象与存储过程或SQL语句进行映射,并提供了普通SQL查询、存储过程和高级映射等操作方式,使得操作数据库变得非常方便。
MyBatis是Apache下的一个开源项目,其前身是iBATIS,它在2002年由Clinton Begin首次发布。2010年5月,该项目由iBATIS更名为MyBatis,同时推出了第一版MyBatis 3,在整个持久层框架市场上引起了很大的关注和广泛的应用。
在iBATIS项目中,XML描述符是核心并且是唯一的形式,它为开发人员提供了很大的灵活性,然而也产生了一些问题,如繁琐、容易出错等。
在MyBatis 3中,Mapper接口和注解成为了主流的配置方式,XML描述符仍然被支持,但不再是唯一的形式。同时,MyBatis 3大量采用了Java 5.0注解,使得代码更加简洁明了。
MyBatis的安装十分简单,只需要在项目的pom.xml文件中添加如下依赖即可:
org.mybatis
mybatis
3.5.7
另外,如果需要使用MyBatis Generator来自动生成Java代码和MyBatis映射文件,则还需要添加如下插件:
org.mybatis.generator
mybatis-generator-maven-plugin
1.4.0
src/main/resources/generatorConfig.xml
true
true
MyBatis并没有内置数据库连接池,因此需要使用第三方的数据库连接池。常见的数据库连接池有如下几种:
在实际使用中,我们可以根据自己的需求选择合适的数据库连接池,这里以HikariCP为例进行演示。可以通过以下方式添加HikariCP的依赖:
com.zaxxer
HikariCP
4.0.3
MyBatis的配置文件是一个XML文件,包含了MyBatis的大部分配置信息,例如数据库连接信息、映射文件位置、缓存配置等。下面是一个简单的MyBatis配置文件样例:
其中,
标签用于指定数据库连接信息,包括事务管理器和数据源信息。这里使用了HikariCP来作为数据源,同时指定了MySQL数据库的连接信息。
标签用于指定映射文件的位置,这里指定了一个映射文件,并指定了它的资源路径。
MyBatis也支持使用YAML格式来进行配置,相对于XML格式更加简洁直观。以下是一个基于YAML格式配置的样例:
# MyBatis 配置
mybatis:
# 别名配置
typeAliasesPackage: com.example.demo.entity
# Mapper XML文件存放路径
mapperLocations: classpath*:mapper/*.xml
# 数据库连接池配置
datasource:
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimumIdle: 5
maximumPoolSize: 20
idleTimeout: 300000
connectionTimeout: 30000
其中,typeAliasesPackage
用于设置实体类的包路径,mapperLocations
用于指定Mapper XML文件的位置,datasource
用于配置数据库连接池,可以设置连接池的参数。
在MyBatis中,还可以使用注解来进行配置,不再需要XML或YAML格式的配置文件。以下是一个基于注解的样例:
// 实体类
public class User {
private Long id;
private String username;
private Integer age;
// getter、setter方法省略
}
// Dao接口
@Mapper
public interface UserDao {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO user(username, age) VALUES (#{username}, #{age})")
int save(User user);
@Update("UPDATE user SET username = #{username}, age = #{age} WHERE id = #{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteById(Long id);
}
// 配置类
@Configuration
@MapperScan("com.example.demo.mapper")
public class MybatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources("classpath*:mapper/*.xml"));
return sessionFactory.getObject();
}
}
以上代码使用了@Mapper
注解来标识Dao接口,并使用@Select
、@Insert
、@Update
、@Delete
等注解来进行SQL操作的配置。在MybatisConfig
中,使用了@MapperScan
注解来指定Mapper类的扫描路径,并使用SqlSessionFactoryBean
来进行SqlSessionFactory的配置。
MyBatis的核心是SQL映射语句,而SQL映射语句则是以XML文件的形式维护在项目中。以下是一个简单的MyBatis映射文件的示例:
INSERT INTO user(username, age)
VALUES (#{username}, #{age})
UPDATE user SET
username = #{username},
age = #{age}
WHERE id = #{id}
DELETE FROM user
WHERE id = #{id}
其中,
标签用于定义命名空间,这里指定了com.example.demo.mapper.UserMapper
作为命名空间。
标签用于定义查询操作,
id
属性表示该SQL语句的唯一标识,parameterType
表示参数类型,resultType
表示返回值类型。在这个例子中,findById
是查询用户信息的语句。
、
、
标签分别表示插入、更新和删除操作,它们的语法与标签类似。
有了映射文件之后,我们就可以使用Java代码来进行数据库操作了。
public interface UserMapper {
// 查询操作
User findById(Long id);
// 插入操作
int save(User user);
// 更新操作
int update(User user);
// 删除操作
int deleteById(Long id);
}
首先定义一个接口,其中包含几个基本的CRUD操作。
@Mapper
public interface UserMapper {
User findById(Long id);
int save(User user);
int update(User user);
int deleteById(Long id);
}
然后使用@Mapper
注解标识该接口为Mapper接口。MyBatis会自动扫描这些接口并创建对应的实现类。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findById(Long id) {
return userMapper.findById(id);
}
@Override
public int save(User user) {
return userMapper.save(user);
}
@Override
public int update(User user) {
return userMapper.update(user);
}
@Override
public int deleteById(Long id) {
return userMapper.deleteById(id);
}
}
最后,在Service层中注入Mapper接口,并使用对应的方法进行数据库操作。
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
在Spring Boot主类中加上@MapperScan
注解,指定Mapper接口的扫描路径。
通过以上步骤,我们就可以完成基本的CRUD操作。
在实际开发中,我们需要根据不同的条件动态生成SQL语句,这时就需要使用MyBatis提供的动态SQL功能。常用的动态SQL元素有if
、where
、foreach
等。
if
元素可以用于根据条件判断是否包含某个SQL语句片段。
例如,我们需要查询年龄大于18岁且小于等于30岁的用户信息,可以这样编写SQL语句:
以上代码中,
元素用于判断minAge
和maxAge
是否为null,如果不为null,则将对应的SQL语句片段拼接到最终的SQL语句中。
where
元素可以用于动态生成WHERE
子句,如果所有条件均为null,则不会生成WHERE
子句。
例如,我们需要查询用户名和密码匹配的用户信息,可以这样编写SQL语句:
以上代码中,
元素用于动态生成WHERE
子句,如果username
和password
均为null,则不会生成WHERE
子句。
foreach
元素可以用于循环遍历一个集合,并将集合中的元素拼接到SQL语句中。
例如,我们需要查询多个用户信息,可以这样编写SQL语句:
以上代码中,
元素用于循环遍历List
类型的参数,并将集合中的元素拼接到SQL语句中。
在MyBatis中,插入操作分为手动指定ID和数据库自动生成ID两种方式。
如果需要手动指定ID,可以这样编写SQL语句:
INSERT INTO user(id, username, password, age)
VALUES (#{id}, #{username}, #{password}, #{age})
以上代码中,将插入的ID值直接作为参数传入插入语句中。
如果需要数据库自动生成ID,可以这样编写SQL语句:
INSERT INTO user(username, password, age)
VALUES (#{username}, #{password}, #{age})
以上代码中,通过useGeneratedKeys="true"
参数告诉MyBatis要求数据库生成主键,并通过keyProperty="id"
参数指定了主键的属性名。这样,当执行插入操作后,主键值将自动赋值到User
对象的id
属性中。
删除操作比较简单,可以这样编写SQL语句:
DELETE FROM user
WHERE id = #{id}
以上代码中,直接通过传入的id
参数进行删除操作。
更新操作也比较简单,可以这样编写SQL语句:
UPDATE user SET
username = #{username},
password = #{password},
age = #{age}
WHERE id = #{id}
以上代码中,通过传入的User
对象进行更新操作
在实际应用中,常常需要进行多表关联查询,MyBatis提供了
和
标签来完成多表关联查询。
例如,我们有两个表,分别是user
表和card
表,每个用户都有一张银行卡,通过userId
列可以进行关联查询。可以这样编写SQL语句:
以上代码中,通过INNER JOIN
连接两个表,并使用u.*
和c.*
来选择需要查询的列。
然而,直接返回结果集会将所有数据都映射到User
对象中,并不符合我们的需求。此时,可以使用
标签来自定义结果映射规则。
以上代码中,
标签定义了结果映射规则,包括主键、普通属性和关联属性。其中,
标签指定了一个一对一关联关系,并通过property
属性指向User
对象中的Card
属性。
例如,我们有两个表,分别是user
表和address
表,每个用户可以有多个地址,通过userId
列可以进行关联查询。可以这样编写SQL语句:
以上代码中,同样使用INNER JOIN
连接两个表。
然而,直接返回结果集会将所有数据都映射到User
对象中,并不符合我们的需求。此时,可以使用
标签来指定一个一对多关联关系,并通过property
属性指向User
对象中的addresses
属性。
以上代码中,
标签指定了一个一对多关联关系,并通过ofType
属性指定目标类型为Address
。
MyBatis提供了缓存机制,这可以有效地减少与数据库的交互次数,提高系统性能。
默认情况下,MyBatis会开启一级缓存(SqlSession级别的缓存)和二级缓存(全局共享的缓存)。
以上代码中,通过配置
标签来启用全局二级缓存,并指定了使用Ehcache作为缓存实现方式。
在自定义Mapper接口中,可以通过@CacheNamespace
注解来启用单独的二级缓存。
@CacheNamespace
public interface UserMapper {
// ...
}
以上代码中,通过@CacheNamespace
注解来启用UserMapper的二级缓存。
需要注意的是,如果在进行insert、update、delete等操作时,MyBatis会清空该namespace下的所有缓存。
MyBatis提供了分页插件,这可以方便地实现分页查询功能。
首先,引入分页插件jar包,例如使用PageHelper插件:
com.github.pagehelper
pagehelper
5.1.11
然后,在MyBatis配置文件中配置分页插件:
最后,在自定义Mapper接口方法中使用分页插件来完成分页查询:
public interface UserMapper {
List findUsersByPage(@Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
}
以上代码中,使用@Param
注解来指定传入的参数名,使用PageHelper插件来实现分页查询。
@Test
public void testFindUsersByPage() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(2, 3);
List users = userMapper.findUsersByPage();
for (User user : users) {
System.out.println(user);
}
PageInfo pageInfo = new PageInfo<>(users);
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("每页记录数:" + pageInfo.getPageSize());
System.out.println("总记录数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("是否第一页:" + pageInfo.isIsFirstPage());
System.out.println("是否最后一页:" + pageInfo.isIsLastPage());
} finally {
sqlSession.close();
}
}
以上代码中,使用PageHelper.startPage()
方法来指定分页查询的页码和每页记录数,使用PageInfo
类来获取分页相关信息。
MyBatis和Spring的整合,可以通过Spring提供的SqlSessionFactoryBean
和MapperScannerConfigurer
来实现。
其中,SqlSessionFactoryBean
负责创建SqlSessionFactory对象,MapperScannerConfigurer
负责将Mapper接口扫描注册到Spring容器中,以便在应用中注入并使用。
首先,引入MyBatis和Spring相关jar包,例如:
org.mybatis
mybatis
3.5.7
org.springframework
spring-context
5.3.6
然后,在Spring配置文件中配置SqlSessionFactoryBean
和MapperScannerConfigurer
:
以上代码中,通过SqlSessionFactoryBean
配置SqlSessionFactory对象,并指定数据源和MyBatis配置文件路径。通过MapperScannerConfigurer
注册Mapper接口,其中basePackage
指定了Mapper接口所在的包路径。
最后,在需要使用Mapper接口的地方,注入该接口,并使用。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(int id) {
return userMapper.getUserById(id);
}
}
以上代码中,通过@Autowired
注解将UserMapper
接口注入到UserServiceImpl
中,并在方法实现中使用该接口。
MyBatis Generator是MyBatis官方提供的一个开源项目,可以根据数据库表自动生成对应的Java实体类、Mapper接口和XML文件,极大地简化了开发工作。
具体来说,MyBatis Generator会根据指定的数据库连接信息、表名规则、生成策略等参数,自动生成Java实体类和Mapper接口。同时,还可以根据表结构自动生成SQL语句,并将其配置到XML文件中,以便直接使用。
通常情况下,MyBatis Generator会为每个表生成3个文件:
src/main/java
下的指定包路径中。src/main/java
下的指定包路径中。src/main/resources
下的指定包路径中。在生成XML文件时,MyBatis Generator提供了不同的生成策略,如:
*Mapper.xml
命名。*Mapper.xml
命名,并在Java类中通过@Mapper
注解来指定XML文件名。首先,引入MyBatis Generator相关jar包和数据库驱动,例如:
org.mybatis.generator
mybatis-generator-core
1.4.0
mysql
mysql-connector-java
8.0.24
然后,在项目根目录下新建一个generatorConfig.xml
配置文件,其中包含数据库连接信息、表名规则、生成策略、Java类型映射等。
以上代码中,通过 通过 最后,在根目录下打开命令行窗口,执行以下命令即可自动生成代码: 其中, 示例:使用MyBatis Generator生成Java实体类、Mapper接口和XML文件,假设有一张名为 首先,在 然后,在根目录下打开命令行窗口,执行以下命令: 执行完成后,可以在指定路径下看到生成的代码文件: MyBatis Plus是一款MyBatis框架的增强工具,提供了很多实用的功能,可以极大地简化开发工作。其主要功能包括: MyBatis Plus的主要优点有: MyBatis Plus的局限性主要有: 首先,在项目中引入MyBatis Plus相关的jar包 MyBatis Plus提供了官方的代码生成器,可以根据数据库表自动生成Java实体类、Mapper接口及其XML文件。使用方法如下: ```properties # 数据库连接信息 spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=root # MyBatis Plus配置 mybatis-plus.mapper-locations=classpath:mapper/*.xml mybatis-plus.type-aliases-package=com.example.entity mybatis-plus.configuration.cache-enabled=false mybatis-plus.global-config.id-type=auto ``` 其中, ```java public class CodeGenerator { public static void main(String[] args) { // 数据源配置 DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL) .setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8") .setUsername("root") .setPassword("root") .setDriverName("com.mysql.cj.jdbc.Driver"); } ``` 其中, 在以上代码中, ```java public class CodeGenerator { public static void main(String[] args) { // ... 使用MyBatis Plus进行Lambda表达式查询,需要先引入LambdaQueryWrapper类,例如: 然后,可以进行如下Lambda表达式查询: 以上代码中, 使用MyBatis Plus进行分页查询可以很简单地实现,例如: 以上代码中,通过 MyBatis Plus提供了多租户插件,可以轻松实现多租户场景。首先,在 其中, 然后,在 以上代码中, 最后,在Mapper接口的查询语句中添加 以上代码中, 最后,在Mapper接口的查询语句中添加 以上代码中, } ``` 在使用MyBatis进行开发之前,首先要掌握好数据表的设计。好的数据表设计可以极大地提高查询效率,降低系统复杂度。下面介绍一些数据表设计的要点。 在设计数据表时,需要考虑好表与表之间的关系,包括一对一、一对多和多对多等关系。下面介绍一些常见的表关系设计。 MyBatis的映射文件用于定义SQL语句和映射规则,下面介绍一些映射文件编写的要点。 以上代码中,使用 子查询指的是将一个SQL语句嵌套到另一个SQL语句中,作为另一个SQL语句的一部分进行查询操作。虽然使用子查询可以实现较为复杂的查询操作,但是也会带来一些性能问题,主要表现在以下几个方面: 因此,在编写SQL语句时,应该尽可能避免使用子查询。可以通过以下几种方式来替代使用子查询的情况: 以下是一个使用多表连接查询替代子查询的示例: %前缀模糊查询指的是在查询字符串时,使用%作为前缀进行模糊匹配。虽然使用%前缀模糊查询可以实现快速查找匹配字符串的功能,但同时也会带来一些性能问题,主要表现在以下几方面: 因此,在编写SQL语句时,应该尽可能避免使用%前缀模糊查询。可以通过以下方式来替代使用%前缀模糊查询的情况: 以下是一个使用全文索引替代%前缀模糊查询的示例: MyBatis作为一款优秀的ORM框架,其使用广泛,功能也非常强大。MyBatis的未来发展方向主要包括以下几个方面: 在使用MyBatis时,需要注意以下事项: 在使用MyBatis过程中,也存在一些常见问题,例如:jdbcConnection
指定数据库连接信息。使用标签指定要生成Java实体类和Mapper接口的表,其中
tableName
指定表名,domainObjectName
指定Java实体类名。
指定Java类型映射,例如将bigint映射到Long类型。通过
、
和
分别设置Java实体类生成路径、Mapper接口生成路径和XML文件生成路径及文件名。$ java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite
mybatis-generator-core-x.x.x.jar
为MyBatis Generator的jar包。-configfile
参数指定配置文件名,-overwrite
参数表示覆盖已有文件。执行完成后,即可在指定路径下看到生成的代码文件。account
的表,该表包含id、name和balance三个字段。generatorConfig.xml
配置文件中添加以下代码:
$ java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite
com.example.entity.Account.java
com.example.mapper.AccountMapper.java
mapper/AccountMapper.xml
3.3 代码生成器:MyBatis Plus
3.3.1 MyBatis Plus简介
3.3.2 MyBatis Plus的优点和局限性
3.3.3 MyBatis Plus的使用
3.3.3.1 引入MyBatis Plus
3.3.3.2 自动生成代码
application.properties
配置文件中,添加以下代码:spring.datasource.url
为数据库连接信息,mybatis-plus.mapper-locations
表示Mapper接口对应的XML文件所在路径,mybatis-plus.type-aliases-package
表示Java实体类所在包路径。
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java")
.setAuthor("binjie09")
.setOpen(false)
.setFileOverride(true)
.setIdType(IdType.AUTO)
.setBaseResultMap(true)
.setBaseColumnList(true);
// 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.example")
.setEntity("entity")
.setMapper("mapper")
.setXml("mapper.xml")
.setService("service")
.setServiceImpl("service.impl")
.setController("controller");
// 策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setCapitalMode(true)
.setNaming(NamingStrategy.underline_to_camel)
.setTablePrefix("t_")
.setInclude("user");
// 代码生成器
AutoGenerator autoGenerator = new AutoGenerator();
autoGenerator.setDataSource(dataSourceConfig)
.setGlobalConfig(globalConfig)
.setPackageInfo(packageConfig)
.setStrategy(strategyConfig)
.execute();
}
dataSourceConfig
为数据源配置,globalConfig
为全局配置,packageConfig
为包配置,strategyConfig
为策略配置。创建了相应的配置后,调用AutoGenerator
的execute()
方法即可生成代码。setInclude("user")
表示只生成user
表对应的Java实体类、Mapper接口及其XML文件,也可不传入参数表示生成所有表的代码。
3.3.3.3 Lambda查询
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List
queryWrapper.like(User::getName, name)
表示查询name
字段包含name
字符串的记录,而User::getName
表示获取User
对象的name
属性。3.3.3.4 分页查询
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public IPage
new Page<>(pageNum, pageSize)
创建了分页对象,即第pageNum
页,每页展示pageSize
条数据。然后,调用IPage
方法进行分页查询。3.3.3.5 多租户支持
application.yml
配置文件中添加以下代码:mybatis-plus:
configuration:
# 指定多租户插件类
plugins: com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
global-config:
# 指定租户ID列名
tenant-id-column: tenant_id
# 指定租户ID处理器
tenant-handler: com.example.handler.MultiTenantHandler
com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
为多租户插件类,tenant-id-column
指定租户ID列名,tenant-handler
指定租户ID处理器。MultiTenantHandler
中编写租户ID过滤逻辑,例如:public class MultiTenantHandler implements TenantHandler {
private static final String DEFAULT_TENANT_ID = "1";
@Override
public Expression getTenantId(boolean where) {
// 获取当前租户ID,可以从Session、ThreadLocal等获取
String tenantId = TenantContext.getTenantId();
// 如果没有获取到租户ID,则使用默认的租户ID
if (tenantId == null || "".equals(tenantId.trim())) {
tenantId = DEFAULT_TENANT_ID;
}
return new LongValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
// 过滤掉不需要进行租户ID过滤的表
return !"user".equalsIgnoreCase(tableName);
}
}
getTenantId()
方法用于获取当前租户ID,getTenantIdColumn()
方法返回租户ID列名,doTableFilter()
方法用于过滤掉不需要进行租户ID过滤的表。@SqlParser(filter=true)
注解即可启用多租户插件,例如:public class MultiTenantHandler implements TenantHandler {
private static final String DEFAULT_TENANT_ID = "1";
@Override
public Expression getTenantId(boolean where) {
// 获取当前租户ID,可以从Session、ThreadLocal等获取
String tenantId = TenantContext.getTenantId();
// 如果没有获取到租户ID,则使用默认的租户ID
if (tenantId == null || "".equals(tenantId.trim())) {
tenantId = DEFAULT_TENANT_ID;
}
return new LongValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
// 过滤掉不需要进行租户ID过滤的表
return !"user".equalsIgnoreCase(tableName);
}
}
getTenantId()
方法用于获取当前租户ID,getTenantIdColumn()
方法返回租户ID列名,doTableFilter()
方法用于过滤掉不需要进行租户ID过滤的表。@SqlParser(filter=true)
注解即可启用多租户插件,例如:@Mapper
public interface UserMapper extends BaseMapper
@SqlParser(filter=true)
注解表示启用过滤器,对selectList()
方法进行租户ID过滤。4. 最佳实践
4.1 掌握MyBatis数据表设计
4.1.1 表设计规范
user_info
。user_id
。id
。VARCHAR(255)
,而不是TEXT
或者MEDIUMTEXT
。4.1.2 表关系设计
4.2 映射文件编写的要点
4.2.1 SQL语句编写
4.2.2 映射规则编写
、
、
等。需要根据不同情况选择合适的映射关系标签。getUserById
、listUsers
等。not-null="true"
表示该属性不能为空。
标签进行分发处理,当查询结果中的type
列值为1
时,使用studentMap
映射;当type
列值为2
时,使用teacherMap
映射.4.3 编写高效的SQL语句
4.3.1 避免使用子查询
-- 子查询
SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE name LIKE '%张三%');
-- 多表连接查询
SELECT o.* FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.name LIKE '%张三%';
4.3.2 避免使用%前缀模糊查询
-- %前缀模糊查询
SELECT * FROM articles WHERE title LIKE '%关键词%';
-- 全文索引查询
SELECT * FROM articles WHERE MATCH(title) AGAINST('关键词' IN NATURAL LANGUAGE MODE);
5. 总结
5.1 MyBatis的未来
5.2 MyBatis的注意事项以及常见问题
你可能感兴趣的:(MyBatis,mybatis)