本文详细介绍了MyBatis教程,涵盖从环境搭建到核心概念详解、CRUD操作实现、动态SQL使用、分页查询、嵌套查询、Spring集成以及调试与性能优化技巧。此外,还提供了丰富的示例代码和配置文件,帮助读者更好地理解和应用MyBatis的相关技术。
MyBatis简介与环境搭建MyBatis是一个优秀的持久层框架,它支持定制化SQL查询,存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(普通的Java对象)映射成数据库中的记录。
MyBatis具有以下优势:
MyBatis适用于以下场景:
创建一个Maven项目,并在pom.xml
中添加MyBatis的依赖:
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- 数据库驱动依赖,以MySQL为例 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <!-- 测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
配置数据库连接信息,例如在src/main/resources
目录下创建一个名为mybatis-config.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="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="password"/> </dataSource> </environment> </environments> </configuration>
创建一个测试类,使用MyBatis进行简单的数据库操作:
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; import java.io.InputStream; import java.util.List; public class MyBatisTest { public static void main(String[] args) throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { List<String> users = session.selectList("com.example.demo.UserMapper.selectAllUsers"); for (String user : users) { System.out.println(user); } } } }
创建一个映射文件UserMapper.xml
,定义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.demo.UserMapper"> <select id="selectAllUsers" resultType="string"> SELECT username FROM users </select> </mapper>
在数据库中创建一个用户表users
,并插入一些测试数据。
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL ); INSERT INTO users (username) VALUES ('Alice'); INSERT INTO users (username) VALUES ('Bob');
修改UserMapper.xml
以使用新的SQL语句。
<mapper namespace="com.example.demo.UserMapper"> <select id="selectAllUsers" resultType="string"> SELECT username FROM users </select> </mapper>
修改Java测试代码以使用新的映射文件。
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; public class MyBatisTest { public static void main(String[] args) throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { List<String> users = session.selectList("com.example.demo.UserMapper.selectAllUsers"); for (String user : users) { System.out.println(user); } } } }
UserMapper.xml
以实现insertUser
、updateUser
和deleteUser
操作。MyBatis的核心配置文件mybatis-config.xml
定义了数据库连接信息、环境配置、映射文件等重要配置。以下是核心配置文件的基本结构和常用配置项:
<configuration> <properties> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="password"/> </properties> <settings> <setting name="cacheEnabled" value="true"/> </settings> <typeAliases> <typeAlias alias="User" type="com.example.demo.User"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/example/demo/UserMapper.xml"/> </mappers> </configuration>
SqlSessionFactory
和SqlSession
是MyBatis的核心对象。
SqlSessionFactory
用于创建SqlSession
对象,是线程安全的,并且只能创建一次。创建SqlSessionFactory
的方法通常是在mybatis-config.xml
配置文件中定义。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession
提供了执行SQL语句所需的方法,包括select
、insert
、update
和delete
等。通常通过SqlSessionFactory
的openSession
方法获取SqlSession
对象。
try (SqlSession session = factory.openSession()) { // 使用session执行SQL语句 }
MyBatis的映射文件(通常是.xml
文件)定义了SQL查询语句及其对应的方法。映射文件中包含多个<mapper>
标签,每个标签定义了一个SQL语句。
<mapper namespace="com.example.demo.UserMapper"> <select id="selectAllUsers" resultType="string"> SELECT username FROM users </select> <insert id="insertUser"> INSERT INTO users (username) VALUES (#{username}) </insert> <update id="updateUser"> UPDATE users SET username=#{username} WHERE id=#{id} </update> <delete id="deleteUser"> DELETE FROM users WHERE id=#{id} </delete> </mapper>
namespace
:命名空间,用于区分不同的映射文件。id
:映射语句的唯一标识符。resultType
:结果类型,可以是Java类型或别名。#{}
:占位符,用于参数传递。通过在Java接口中定义方法,并在映射文件中指定方法名,可以简化映射文件的配置。
public interface UserMapper { List<String> selectAllUsers(); void insertUser(String username); void updateUser(String username, int id); void deleteUser(int id); }
<mapper namespace="com.example.demo.UserMapper"> <select id="selectAllUsers" resultType="string"> SELECT username FROM users </select> <insert id="insertUser"> INSERT INTO users (username) VALUES (#{username}) </insert> <update id="updateUser"> UPDATE users SET username=#{username} WHERE id=#{id} </update> <delete id="deleteUser"> DELETE FROM users WHERE id=#{id} </delete> </mapper>
selectAllUsers
、insertUser
、updateUser
、deleteUser
)。CRUD操作是指创建(Create)、读取(Read)、更新(Update)和删除(Delete)操作。以下是CRUD操作的实现步骤:
SqlSession
的insert
方法执行插入语句。public interface UserMapper { void insertUser(String username); } // 映射文件 <insert id="insertUser"> INSERT INTO users (username) VALUES (#{username}) </insert>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.insertUser("Alice"); session.commit(); }
SqlSession
的select
方法执行查询语句。public interface UserMapper { List<String> selectAllUsers(); } // 映射文件 <select id="selectAllUsers" resultType="string"> SELECT username FROM users </select>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); List<String> users = mapper.selectAllUsers(); for (String user : users) { System.out.println(user); } }
SqlSession
的update
方法执行更新语句。public interface UserMapper { void updateUser(String username, int id); } // 映射文件 <update id="updateUser"> UPDATE users SET username=#{username} WHERE id=#{id} </update>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.updateUser("Bob", 1); session.commit(); }
SqlSession
的delete
方法执行删除语句。public interface UserMapper { void deleteUser(int id); } // 映射文件 <delete id="deleteUser"> DELETE FROM users WHERE id=#{id} </delete>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteUser(1); session.commit(); }
MyBatis支持注解来简化映射文件的配置。例如,@Select
、@Insert
、@Update
和@Delete
注解可以用于Java接口中定义的方法。
使用@Select
注解定义查询方法。
public interface UserMapper { @Select("SELECT username FROM users") List<String> selectAllUsers(); }
使用@Insert
注解定义插入方法。
public interface UserMapper { @Insert("INSERT INTO users (username) VALUES (#{username})") void insertUser(String username); }
使用@Update
注解定义更新方法。
public interface UserMapper { @Update("UPDATE users SET username=#{username} WHERE id=#{id}") void updateUser(String username, int id); }
使用@Delete
注解定义删除方法。
public interface UserMapper { @Delete("DELETE FROM users WHERE id=#{id}") void deleteUser(int id); }
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.insertUser("Alice"); mapper.updateUser("Bob", 1); mapper.deleteUser(1); List<String> users = mapper.selectAllUsers(); for (String user : users) { System.out.println(user); } session.commit(); }
复杂的查询通常涉及到连接查询、子查询等。例如,查询所有用户的姓名及其所属的部门。
SELECT users.username, departments.department_name FROM users JOIN departments ON users.department_id = departments.id
在映射文件中定义该查询:
<select id="selectAllUsersWithDepartments" resultType="com.example.demo.UserDepartment"> SELECT users.username, departments.department_name FROM users JOIN departments ON users.department_id = departments.id </select>
复杂的更新可能涉及到多个表的更新。例如,更新用户信息的同时更新其所属的部门信息。
UPDATE users SET username = #{username} WHERE id = #{id}
UPDATE departments SET department_name = #{departmentName} WHERE id = #{departmentId}
在映射文件中定义这些更新语句:
<update id="updateUserAndDepartment"> UPDATE users SET username = #{username} WHERE id = #{id} UPDATE departments SET department_name = #{departmentName} WHERE id = #{departmentId} </update>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); mapper.updateUserAndDepartment("Alice", 1, "Engineering"); session.commit(); }
动态SQL是指根据不同的条件生成不同的SQL语句。例如,根据用户输入的不同条件动态生成查询语句。动态SQL的使用场景包括:
MyBatis提供了<if>
、<choose>
、<when>
和<otherwise>
标签来实现动态SQL。
<if>
标签用于根据条件动态生成SQL语句的一部分。
<select id="selectUsersByCondition" resultType="string"> SELECT username FROM users <where> <if test="username != null"> AND username = #{username} </if> <if test="id != null"> AND id = #{id} </if> </where> </select>
<choose>
标签用于选择一组条件中的一个进行匹配。
<select id="selectUsersByCondition" resultType="string"> SELECT username FROM users <where> <choose> <when test="username != null"> AND username = #{username} </when> <when test="id != null"> AND id = #{id} </when> <otherwise> AND id = 1 </otherwise> </choose> </where> </select>
<when>
标签用于定义条件分支。
<otherwise>
标签用于定义默认情况。
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); List<String> users = mapper.selectUsersByCondition(null, 1); for (String user : users) { System.out.println(user); } users = mapper.selectUsersByCondition("Alice", null); for (String user : users) { System.out.println(user); } }
分页查询通常使用SQL的LIMIT
关键字实现。例如,查询第一页第1到10条记录。
SELECT username FROM users LIMIT 0, 10
在映射文件中定义分页查询:
<select id="selectAllUsersWithPage" resultType="string"> SELECT username FROM users <if test="offset != null and limit != null"> LIMIT #{offset}, #{limit} </if> </select>
嵌套查询通常用于查询一个表中的数据,再根据该表数据查询另一个表的数据。例如,查询所有用户的姓名及其所属的部门。
SELECT users.username, departments.department_name FROM users JOIN departments ON users.department_id = departments.id
在映射文件中定义嵌套查询:
<select id="selectAllUsersWithDepartments" resultType="com.example.demo.UserDepartment"> SELECT users.username, departments.department_name FROM users JOIN departments ON users.department_id = departments.id </select>
try (SqlSession session = factory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); List<String> users = mapper.selectAllUsersWithPage(0, 10); for (String user : users) { System.out.println(user); } List<UserDepartment> userDepartments = mapper.selectAllUsersWithDepartments(); for (UserDepartment userDepartment : userDepartments) { System.out.println(userDepartment.getUsername() + ": " + userDepartment.getDepartmentName()); } }
Spring是一个流行的Java应用框架,它提供了多种功能,包括依赖注入、事务管理等。Spring与MyBatis集成的目的在于:
通过在Spring配置文件中定义MyBatis的配置,可以简化MyBatis的管理和依赖注入。
在Spring配置文件中定义MyBatis配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.demo.mapper"/> </bean>
在pom.xml
中添加Spring的依赖:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.10</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> </dependencies>
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class SpringMyBatisTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean(UserMapper.class); List<String> users = userMapper.selectAllUsers(); for (String user : users) { System.out.println(user); } } }
通过Spring管理MyBatis的事务管理,可以简化事务的管理。
在Spring配置文件中定义事务管理:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
通过@Transactional
注解实现事务管理。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserService { @Autowired private UserMapper userMapper; @Transactional public void createUser(String username) { userMapper.insertUser(username); } }
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringMyBatisTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean(UserService.class); userService.createUser("Alice"); } }
MyBatis的调试可以通过配置日志级别和使用调试工具来实现。
在mybatis-config.xml
中配置日志级别:
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
使用IDE的调试工具或MyBatis的调试工具进行调试。
常见的MyBatis错误包括SQL语法错误、配置错误、类型映射错误等。
确保SQL语句正确无误。
检查mybatis-config.xml
和映射文件的配置是否正确。
确保Java对象和数据库字段的类型映射正确。
性能优化可以通过以下方法实现:
启用MyBatis的缓存功能:
<settings> <setting name="cacheEnabled" value="true"/> </settings>
通过分页查询和嵌套查询减少查询次数:
<select id="selectAllUsersWithPage" resultType="string"> SELECT username FROM users <if test="offset != null and limit != null"> LIMIT #{offset}, #{limit} </if> </select>
优化SQL语句以提高查询性能:
SELECT username FROM users WHERE username LIKE #{username} ESCAPE '\\'
通过以上详细的步骤和示例代码,你可以深入学习和掌握MyBatis的核心概念、配置、操作以及调试技巧,从而更好地应用于实际开发中。