1、什么是 MyBatis
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
2、优点
- 灵活性高:MyBatis不会对应用程序或数据库的现有设计强加任何影响,开发人员可以使用他们已经熟悉的SQL语句、存储过程和数据库触发器等
- SQL可控性强:对于复杂查询和多表关联查询时,MyBatis的优势尤为明显,因为可以更加灵活地控制生成的SQL语句,并在需要的情况下针对不同的数据库实现进行优化。
- 缓存机制好:MyBatis提供了一级缓存和二级缓存,可以有效地减少数据库访问次数,提高响应速度,而且它们的使用非常方便,并且默认情况下处于开启状态。
- 生态系统完善:MyBatis有着非常强大的社区支持,同时它也与Spring,Spring Boot等流行框架或中间件无缝整合,方便企业级项目的开发。
3、缺点
- 性能问题:相比于Hibernate等ORM框架,在大规模数据处理能力和并发性方面,MyBatis的性能表现略逊一筹。
- 配置复杂:相比Hibernate等ORM框架,MyBatis的配置文件相对较为复杂,需要花费更多的时间和精力进行配置。
- 映射错误难以追踪:由于映射文件是通过XML描述符或注解进行的,为了解决常见的SQL问题,需要对SQL语句的编写和映射文件的正确描述非常敏感,出现异常时排查起来也较为繁琐。
4、MyBatis的安装
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
自动生成Java代码和MyBatis映射文件
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<!-- MyBatis Generator配置文件的位置 -->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
</plugins>
5、数据库连接池
MyBatis并没有内置数据库连接池,因此需要使用第三方的数据库连接池。常见的数据库连接池有如下几种:
- HikariCP:性能最好的连接池,也是目前最流行的连接池之一。
- Apache Commons DBCP2:Apache官方开发的连接池,支持连接池配置和管理、连接有效性验证、闲置连接回收等功能。
- Alibaba Druid:阿里巴巴开发的连接池,支持JDBC规范、多数据源、SQL防注入、监控等功能。
<dependencies>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies>
6、MyBatis配置方式
6.1、基于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="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 扫描映射文件 -->
<mappers>
<mapper resource="com/example/demo/mapper/UserMapper.xml"/>
</mappers>
</configuration>
6.2、基于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
6.3、基于注解配置文配置
/ 实体类
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();
}
}
7、MyBatis使用
7.1、Java类
@Mapper
public interface UserMapper {
User findById(Long id);
int save(User user);
int update(User user);
int deleteById(Long id);
}
7.2、mapper文件
<?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.demo.mapper.UserMapper">
<!-- 查询操作 -->
<select id="findById" parameterType="Long" resultType="User">
SELECT *
FROM user
WHERE id = #{id}
</select>
<!-- 插入操作 -->
<insert id="save" parameterType="User">
INSERT INTO user(username, age)
VALUES (#{username}, #{age})
</insert>
<!-- 更新操作 -->
<update id="update" parameterType="User">
UPDATE user SET
username = #{username},
age = #{age}
WHERE id = #{id}
</update>
<!-- 删除操作 -->
<delete id="deleteById" parameterType="Long">
DELETE FROM user
WHERE id = #{id}
</delete>
</mapper>
8、MyBatis的注意事项以及常见问题
在使用MyBatis时,需要注意以下事项:
- 避免使用SELECT *:使用明确指出需要查询的字段,而不是查询全部字段,可以提高查询效率。
- 显式指定参数类型:在使用Mapper接口调用SQL查询时,参数类型必须与Mapper接口方法参数类型一致或者符合JavaBean规范。
- 使用动态SQL:可以根据不同的条件排除或者包含某个SQL片段,以达到避免重复代码的作用。
- 使用缓存:MyBatis支持多种缓存方式,可以提高查询效率。但是需要注意缓存更新策略,以免出现数据不一致问题。
- 配置文件管理:MyBatis的配置文件中包含了许多的配置信息,需要注意配置信息的管理和维护。
在使用MyBatis过程中,也存在一些常见问题,例如:
- 多表查询使用联合查询的性能问题。
- 分页查询时,使用游标或者取所有数据的性能问题。
- MyBatis缓存机制带来的数据不一致问题。
- SQL语句过于复杂,导致难以调试和维护。
- 数据库连接池的优化问题。