赞
踩
MyBatis 是一个持久化框架(persistence framework),它简化了对数据库的访问,同时又保留了对 SQL 的控制。它在数据持久化的过程中,避免了大量的 JDBC 代码以及手动设置参数和获取结果的繁琐步骤。相比于 Hibernate 等全自动 ORM 框架,MyBatis 更轻量级且灵活,特别适用于需要手写复杂 SQL 的场景。接下来,我们将详细介绍 MyBatis 的各个方面。
MyBatis 是 Apache Software Foundation 旗下的一个项目,用于在 Java 应用中处理持久化层(Persistence Layer)。它通过 XML 或注解的方式将实体类和 SQL 语句进行映射,可以帮助开发者快速进行 CRUD(Create、Read、Update、Delete)操作。
SqlSession
实例。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.selectUserById(1);
// 其他操作
session.commit(); // 提交事务
}
public interface UserMapper {
User selectUserById(int id);
void insertUser(User user);
List<User> selectAllUsers();
}
public class User {
private int id;
private String username;
private String password;
private String email;
// getter 和 setter 方法
}
MyBatis 的配置文件是整个框架的核心,它定义了数据库连接、事务管理、Mapper 映射等。
mybatis-config.xml
。配置多个环境(development、test、production):
<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/testdb?useSSL=false&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="password"/> </dataSource> </environment> <environment id="production"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://production-db:3306/proddb?useSSL=false&serverTimezone=UTC"/> <property name="username" value="prod_user"/> <property name="password" value="prod_password"/> </dataSource> </environment> </environments>
default
:指定默认环境。transactionManager
:
JDBC
:使用 JDBC 提供的事务管理。MANAGED
:应用服务器或 Spring 管理事务。dataSource
:
UNPOOLED
:每次请求都会创建新连接,适用于简单应用。POOLED
:使用连接池提高性能,适用于生产环境。JNDI
:使用应用服务器的数据源。<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
<mappers>
<mapper class="com.example.mapper.UserMapper"/>
</mappers>
<mappers>
<package name="com.example.mapper"/>
</mappers>
类型别名用于简化 XML 中类的引用,可以为常用类指定简短别名。
<typeAliases>
<typeAlias type="com.example.entity.User" alias="User"/>
</typeAliases>
可以使用包扫描自动为包下的类生成别名:
<typeAliases>
<package name="com.example.entity"/>
</typeAliases>
MyBatis 支持插件扩展,可以通过插件实现自定义功能,如日志、分页等。
<plugins>
<plugin interceptor="com.example.plugin.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
</settings>
cacheEnabled
:启用或禁用二级缓存。lazyLoadingEnabled
:启用或禁用延迟加载。useGeneratedKeys
:允许 JDBC 支持生成主键。defaultExecutorType
:
SIMPLE
:每次执行都会打开和关闭 Statement。REUSE
:复用 Statement。BATCH
:批量执行 Statement。defaultStatementTimeout
:设置超时时间(秒)。MyBatis 提供了默认类型处理器,也支持自定义处理器来处理特殊类型。
<typeHandlers>
<typeHandler javaType="java.util.Date" jdbcType="TIMESTAMP" handler="com.example.handler.DateTypeHandler"/>
</typeHandlers>
自定义类型处理器示例:
package com.example.handler; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Date; public class DateTypeHandler extends BaseTypeHandler<Date> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException { ps.setTimestamp(i, new Timestamp(parameter.getTime())); } @Override public Date getNullableResult(ResultSet rs, String columnName) throws SQLException { Timestamp timestamp = rs.getTimestamp(columnName); return timestamp != null ? new Date(timestamp.getTime()) : null; } @Override public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException { Timestamp timestamp = rs.getTimestamp(columnIndex); return timestamp != null ? new Date(timestamp.getTime()) : null; } @Override public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { Timestamp timestamp = cs.getTimestamp(columnIndex); return timestamp != null ? new Date(timestamp.getTime()) : null; } }
MyBatis 支持多种日志框架,包括 SLF4J、Log4j、Commons Logging、JDK Logging。
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
可以在log4j.properties
中配置日志级别:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n
Mapper 文件是 MyBatis 中的核心组件,它定义了 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"> <!-- ResultMap 定义 --> <resultMap id="userResultMap" type="com.example.entity.User"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="email" column="email"/> </resultMap> <!-- SQL 片段 --> <sql id="selectAllFields"> id, username, password, email </sql> <!-- 查询操作 --> <select id="selectUserById" resultMap="userResultMap" parameterType="int"> SELECT <include refid="selectAllFields"/> FROM users WHERE id = #{id} </select> <!-- 插入操作 --> <insert id="insertUser" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email}) </insert> <!-- 更新操作 --> <update id="updateUser" parameterType="com.example.entity.User"> UPDATE users SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id} </update> <!-- 删除操作 --> <delete id="deleteUser" parameterType="int"> DELETE FROM users WHERE id = #{id} </delete> </mapper>
namespace
:定义 Mapper 的命名空间,通常与 Mapper 接口的全限定名相同。resultMap
:用于定义结果集与实体类属性的映射关系。sql
:用于定义可重用的 SQL 片段。select
、insert
、update
、delete
:分别定义查询、插入、更新、删除操作。ResultMap
用于将查询结果与实体类属性进行映射。
<resultMap id="userResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
</resultMap>
id
:映射主键字段。result
:映射非主键字段。SQL 片段可以提高 SQL 语句的重用性。
<sql id="selectAllFields">
id, username, password, email
</sql>
使用 <include>
标签引入 SQL 片段:
<select id="selectUserById" resultMap="userResultMap" parameterType="int">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE id = #{id}
</select>
MyBatis 支持动态 SQL,可以根据不同的条件动态生成 SQL 语句。
<if>
标签<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE 1=1
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
<choose>
标签<select id="selectUser" resultMap="userResultMap" parameterType="map"> SELECT <include refid="selectAllFields"/> FROM users <where> <choose> <when test="username != null"> username = #{username} </when> <when test="email != null"> email = #{email} </when> <otherwise> id = #{id} </otherwise> </choose> </where> </select>
<foreach>
标签<select id="selectUsersByIds" resultMap="userResultMap" parameterType="list">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<trim>
标签<trim>
标签用于动态地移除多余的 SQL 关键字,如 AND
、OR
等。
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</trim>
</select>
<set>
标签<set>
标签用于动态生成 SET
子句,用于 UPDATE
语句中。
<update id="updateUser" parameterType="com.example.entity.User">
UPDATE users
<set>
<if test="username != null">
username = #{username},
</if>
<if test="password != null">
password = #{password},
</if>
<if test="email != null">
email = #{email}
</if>
</set>
WHERE id = #{id}
</update>
<where>
标签<where>
标签用于动态生成 WHERE
子句,会自动去除多余的 AND
、OR
等关键字。
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
Mapper 接口是 MyBatis 的核心组件之一,它定义了数据库操作的方法。
package com.example.mapper; import com.example.entity.User; import org.apache.ibatis.annotations.*; import java.util.List; public interface UserMapper { @Insert("INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email})") @Options(useGeneratedKeys = true, keyProperty = "id") void insertUser(User user); @Select("SELECT * FROM users WHERE id = #{id}") User selectUserById(@Param("id") int id); @Select("SELECT * FROM users") List<User> selectAllUsers(); @Update("UPDATE users SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}") void updateUser(User user); @Delete("DELETE FROM users WHERE id = #{id}") void deleteUser(@Param("id") int id); }
@Insert
:定义插入 SQL 语句。@Select
:定义查询 SQL 语句。@Update
:定义更新 SQL 语句。@Delete
:定义删除 SQL 语句。@Options
:用于配置附加选项,如自动生成主键。@Param
:用于指定参数名称,解决参数名不匹配的问题。Mapper 接口方法的返回值类型可以是以下几种:
int
、String
等。void
:用于插入、更新、删除操作。Mapper 接口方法的参数可以是以下几种:
如基本类型、对象。
@Param
注解指定参数名称。List
、Map
等。MyBatis 可以与 Spring 框架无缝整合,通过 Spring 管理 MyBatis 的 SqlSessionFactory 和事务。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/example/mapper/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
使用 Java 配置替代 XML 配置:
package com.example.config; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration @MapperScan(basePackages = "com.example.mapper") public class MyBatisConfig { @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/example/mapper/*.xml")); return sessionFactory.getObject(); } }
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.mapper.UserMapper; import com.example.entity.User; @Service public class UserService { @Autowired private UserMapper userMapper; @Transactional public void createUser(User user) { userMapper.insertUser(user); } @Transactional(readOnly = true) public User getUserById(int id) { return userMapper.selectUserById(id); } }
MyBatis 提供了一级缓存和二级缓存机制,以提高性能。
<cache/>
MyBatis 支持自定义缓存,可以通过实现 Cache
接口来自定义缓存行为。
package com.example.cache; import org.apache.ibatis.cache.Cache; import java.util.concurrent.locks.ReadWriteLock; public class CustomCache implements Cache { private final String id; public CustomCache(String id) { this.id = id; } @Override public String getId() { return this.id; } @Override public void putObject(Object key, Object value) { // 自定义缓存实现 } @Override public Object getObject(Object key) { // 自定义缓存实现 return null; } @Override public Object removeObject(Object key) { // 自定义缓存实现 return null; } @Override public void clear() { // 自定义缓存实现 } @Override public int getSize() { // 自定义缓存实现 return 0; } @Override public ReadWriteLock getReadWriteLock() { return null; } }
配置自定义缓存:
<cache type="com.example.cache.CustomCache"/>
MyBatis 不支持分页功能,但可以通过插件实现分页。
<plugins>
<plugin interceptor="com.example.plugin.PaginationInterceptor">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
分页插件示例:
package com.example.plugin; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.sql.Connection; import java.util.Properties; @Intercept s({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class PaginationInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { // 拦截逻辑 return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 设置属性 } }
MyBatis 支持插件机制,可以通过拦截器实现自定义功能,如分页、日志记录等。
package com.example.interceptor; import org.apache.ibatis.plugin.*; import java.util.Properties; @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class MyInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { // 拦截逻辑 return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 设置属性 } }
配置自定义拦截器:
<plugins>
<plugin interceptor="com.example.interceptor.MyInterceptor">
<property name="propertyName" value="propertyValue"/>
</plugin>
</plugins>
MyBatis 提供了日志拦截器,可以用于记录 SQL 语句执行的详细信息。
配置日志拦截器:
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
使用 Log4j 记录 SQL 日志:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n
MyBatis Generator 是一个代码生成工具,可以根据数据库表结构生成实体类、Mapper 接口和 Mapper XML 文件。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testdb" userId="root" password="password"/> <javaModelGenerator targetPackage="com.example.entity" targetProject="src/main/java"/> <sqlMapGenerator targetPackage="com.example.mapper" targetProject="src/main/resources"/> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mapper" targetProject="src/main/java"/> <table tableName="users" domainObjectName="User"/> </context> </generatorConfiguration>
可以通过命令行或 Maven 插件运行 MyBatis Generator。
java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite
在 pom.xml
中添加插件配置:
<build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.4.0</version> <executions> <execution> <id>generate-sources</id> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin> </plugins> </build>
执行 Maven 命令:
mvn mybatis-generator:generate
MyBatis 是一款强大的持久层框架,提供了灵活的 SQL 映射和强大的动态 SQL 功能,能够与 Spring 框架无缝整合,支持缓存、插件、拦截器等高级特性,是 Java 开发中常用的持久层解决方案之一。
通过本文档的介绍,您可以掌握 MyBatis 的基本使用方法和高级特性,能够在项目中灵活运用 MyBatis 进行数据库操作。
以上是关于 MyBatis 的详细介绍和使用指南,希望能够帮助您更好地理解和使用 MyBatis。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。