MyBatisX 是一个基于 MyBatis 的增强框架,简化了数据库操作并提供了更多功能;本文将详细介绍如何搭建开发环境并进行项目初始化;通过具体示例演示基本的 CRUD 操作和动态 SQL 的使用;帮助读者掌握 MyBatisX 项目实战技巧与方法。
MyBatisX简介与环境搭建 MyBatisX是什么MyBatisX 是一个基于 MyBatis 的增强框架,它简化了 MyBatis 的配置和使用过程,提供了更多的功能,使开发人员能够更高效地进行数据库操作。MyBatisX 保留了 MyBatis 的核心功能,同时添加了一些高级特性,如自动映射、动态 SQL 支持、缓存等。这些特性使得 MyBatisX 成为一个更加强大和易用的框架。
开发环境搭建IDE选择
MyBatisX 可以在多种IDE中使用,常用的有 IntelliJ IDEA 和 Eclipse 等。这里以 IntelliJ IDEA 为例进行介绍。
依赖库安装
要在项目中使用 MyBatisX,首先需要在项目中引入 MyBatisX 和相关数据库驱动的依赖。通常使用 Maven 或 Gradle 管理项目依赖。
Maven 配置
在 Maven 项目的 pom.xml
文件中添加 MyBatisX 依赖:
<dependencies>
<dependency>
<groupId>com.github.abel5/mapper</groupId>
<artifactId>mybatis-x</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
</dependencies>
项目初始化
创建一个新的 Maven 项目,并添加上述依赖项。项目结构如下:
mybatis-x-project
│
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com.example.demo
│ │ │ ├── mapper
│ │ │ │ └── UserMapper.java
│ │ │ ├── model
│ │ │ │ └── User.java
│ │ │ └── MyBatisXApp.java
│ │ └── resources
│ │ ├── mapper
│ │ │ └── UserMapper.xml
│ │ └── mybatis-x-config.xml
│ └── test
│ └── java
│ └── com.example.demo
│ └── MyBatisXAppTest.java
└── pom.xml
项目初始化
创建一些基本的文件结构,如下:
package com.example.demo.model;
public class User {
private int id;
private String name;
private String email;
public User() {}
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
创建 UserMapper.java
文件:
package com.example.demo.mapper;
import com.example.demo.model.User;
import java.util.List;
public interface UserMapper {
List<User> selectAllUsers();
User selectUserById(int id);
int insertUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
创建 UserMapper.xml
文件:
<?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="selectAllUsers" resultType="com.example.demo.model.User">
SELECT * FROM users
</select>
<select id="selectUserById" resultType="com.example.demo.model.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>
创建 mybatis-x-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>
<typeAliases>
<typeAlias type="com.example.demo.model.User" alias="User"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisx"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
创建主程序 MyBatisXApp.java
:
package com.example.demo;
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.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisXApp {
public static void main(String[] args) throws IOException {
String resource = "mybatis-x-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
System.out.println("Users: ");
List<User> users = mapper.selectAllUsers();
for (User user : users) {
System.out.println(user);
}
}
}
}
MyBatisX核心概念解析
数据库配置文件
数据库配置文件 mybatis-x-config.xml
是 MyBatisX 的核心配置文件,它定义了数据库连接信息、事务管理器、映射文件的位置等关键信息。
配置内容
typeAliases
:定义所有别名environments
:定义可用的环境dataSource
:定义数据源mappers
:定义映射文件的位置
示例配置文件 mybatis-x-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>
<typeAliases>
<typeAlias type="com.example.demo.model.User" alias="User"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisx"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
SQL映射文件
SQL映射文件 UserMapper.xml
定义了操作数据库的具体 SQL 语句和映射规则。这些文件通常位于 src/main/resources/mapper/
目录下。映射文件的根元素是 mapper
,它有一个 namespace
属性,该属性必须与 mapper
接口的全限定名一致。
配置内容
select
:查询操作insert
:插入操作update
:更新操作delete
:删除操作
示例映射文件 UserMapper.xml
如下:
<?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="selectAllUsers" resultType="com.example.demo.model.User">
SELECT * FROM users
</select>
<select id="selectUserById" resultType="com.example.demo.model.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接口定义
实体类 User.java
定义了数据库表的 Java 对象,而 UserMapper.java
定义了数据库操作的接口。
实体类
实体类 User.java
如下:
package com.example.demo.model;
public class User {
private int id;
private String name;
private String email;
public User() {}
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
Mapper接口
Mapper接口 UserMapper.java
如下:
package com.example.demo.mapper;
import com.example.demo.model.User;
import java.util.List;
public interface UserMapper {
List<User> selectAllUsers();
User selectUserById(int id);
int insertUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
基本CRUD操作详解
查询操作
查询操作可以分为单条数据查询和多条数据查询。
单条数据查询
单条数据查询通过 selectUserById
方法实现。该方法接受一个 int
类型的参数 id
,并返回一个 User
对象。
示例代码如下:
User user = mapper.selectUserById(1);
System.out.println("User: " + user);
多条数据查询
多条数据查询通过 selectAllUsers
方法实现。该方法返回一个 List<User>
对象,包含所有用户的列表。
示例代码如下:
List<User> users = mapper.selectAllUsers();
for (User user : users) {
System.out.println("User: " + user);
}
插入操作
插入操作通过 insertUser
方法实现。该方法接受一个 User
对象作为参数,并返回插入操作的影响行数。
示例代码如下:
User user = new User(0, "John Doe", "[email protected]");
int rows = mapper.insertUser(user);
System.out.println("Inserted " + rows + " rows");
更新操作
更新操作通过 updateUser
方法实现。该方法接受一个 User
对象作为参数,并返回更新操作的影响行数。
示例代码如下:
User user = new User(1, "Jane Doe", "[email protected]");
int rows = mapper.updateUser(user);
System.out.println("Updated " + rows + " rows");
删除操作
删除操作通过 deleteUser
方法实现。该方法接受一个 int
类型的参数 id
,并返回删除操作的影响行数。
示例代码如下:
int rows = mapper.deleteUser(1);
System.out.println("Deleted " + rows + " rows");
Service层和Controller层代码实现
假设我们有一个 UserService
服务层和一个 UserController
控制器层。
UserService.java
package com.example.demo.service;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
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 UserService {
private SqlSessionFactory sqlSessionFactory;
private UserMapper userMapper;
public UserService(InputStream inputStream) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
userMapper = sqlSessionFactory.openSession().getMapper(UserMapper.class);
}
public List<User> getAllUsers() {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
return userMapper.selectAllUsers();
}
}
public User getUserById(int id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
return userMapper.selectUserById(id);
}
}
public void addUser(User user) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.insertUser(user);
session.commit();
}
}
public void updateUser(User user) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.updateUser(user);
session.commit();
}
}
public void deleteUser(int id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.deleteUser(id);
session.commit();
}
}
}
UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.web.bind.annotation.*;
import java.io.InputStream;
import java.util.List;
@RestController
public class UserController {
private UserService userService;
public UserController() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("mybatis-x-config.xml");
userService = new UserService(inputStream);
}
@GetMapping("/users")
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/users/{id}")
public User getUserById(@PathVariable int id) {
return userService.getUserById(id);
}
@PostMapping("/users")
public void addUser(@RequestBody User user) {
userService.addUser(user);
}
@PutMapping("/users/{id}")
public void updateUser(@PathVariable int id, @RequestBody User user) {
user.setId(id);
userService.updateUser(user);
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id) {
userService.deleteUser(id);
}
}
动态SQL与高级查询技巧
使用Where子句
动态 SQL 是 MyBatisX 的一个重要特性。通过使用 where
标签,可以根据传入的参数动态生成 WHERE
子句。
示例
假设我们有一个 UserMapper
接口,其中有一个根据条件查询用户的方法:
package com.example.demo.mapper;
import com.example.demo.model.User;
import java.util.List;
public interface UserMapper {
List<User> selectUsersByCondition(String name, String email);
}
对应的 UserMapper.xml
配置如下:
<sql id="Base_Column_List">
id, name, email
</sql>
<select id="selectUsersByCondition" resultType="com.example.demo.model.User">
SELECT <include refid="Base_Column_List"/>
FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
示例代码
List<User> users = mapper.selectUsersByCondition("John Doe", null);
for (User user : users) {
System.out.println("User: " + user);
}
参数传递与结果映射
MyBatisX 支持多种参数类型和结果映射方式,包括单个参数、多个参数、复杂参数等。
单个参数
单个参数可以通过 #{}
占位符传递到 SQL 语句中。
示例代码如下:
User user = mapper.selectUserById(1);
System.out.println("User: " + user);
多个参数
多个参数可以通过 #{}
占位符传递到 SQL 语句中,同时也可以通过 param
标签指定参数名称。
示例代码如下:
List<User> users = mapper.selectUsersByCondition("John Doe", "[email protected]");
for (User user : users) {
System.out.println("User: " + user);
}
复杂参数
复杂参数可以通过 #{}
占位符传递到 SQL 语句中,同时也可以通过 param
标签指定参数名称,并且可以传递 Java 对象作为参数。
示例代码如下:
class UserCondition {
private String name;
private String email;
// Getter 和 Setter 方法
}
UserCondition condition = new UserCondition();
condition.setName("John Doe");
condition.setEmail("[email protected]");
List<User> users = mapper.selectUsersByCondition(condition);
for (User user : users) {
System.out.println("User: " + user);
}
结果映射
结果映射可以通过 resultType
或 resultMap
标签指定。
示例代码如下:
<resultMap id="UserResultMap" type="com.example.demo.model.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
</resultMap>
<select id="selectUserById" resultMap="UserResultMap">
SELECT * FROM users WHERE id = #{id}
</select>
聚合函数和分页查询
聚合函数
MyBatisX 支持使用聚合函数,如 COUNT
, SUM
, AVG
, MIN
, MAX
等。
示例代码如下:
int count = mapper.countUsers();
System.out.println("Total users: " + count);
double average = mapper.averageAge();
System.out.println("Average age: " + average);
分页查询
分页查询可以通过 LIMIT
和 OFFSET
关键字实现。
示例代码如下:
package com.example.demo.mapper;
import com.example.demo.model.User;
import java.util.List;
public interface UserMapper {
List<User> selectUsersByPage(int offset, int limit);
}
对应的 UserMapper.xml
配置如下:
<select id="selectUsersByPage" resultType="com.example.demo.model.User">
SELECT * FROM users LIMIT #{offset}, #{limit}
</select>
示例代码
List<User> users = mapper.selectUsersByPage(0, 10);
for (User user : users) {
System.out.println("User: " + user);
}
实战案例:创建简单的CRUD应用
设计数据库表结构
首先,设计一个简单的数据库表结构。这里我们创建一个名为 users
的表,包含 id
, name
, email
三个字段。
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL
);
编写Mapper接口和映射文件
在 UserMapper.java
和 UserMapper.xml
文件中定义 CRUD 操作。
UserMapper.java
package com.example.demo.mapper;
import com.example.demo.model.User;
import java.util.List;
public interface UserMapper {
List<User> selectAllUsers();
User selectUserById(int id);
int insertUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
UserMapper.xml
<?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="selectAllUsers" resultType="com.example.demo.model.User">
SELECT * FROM users
</select>
<select id="selectUserById" resultType="com.example.demo.model.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>
编写Service层和Controller层代码
假设我们有一个 UserService
服务层和一个 UserController
控制器层。
UserService.java
package com.example.demo.service;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
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 UserService {
private SqlSessionFactory sqlSessionFactory;
private UserMapper userMapper;
public UserService(InputStream inputStream) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
userMapper = sqlSessionFactory.openSession().getMapper(UserMapper.class);
}
public List<User> getAllUsers() {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
return userMapper.selectAllUsers();
}
}
public User getUserById(int id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
return userMapper.selectUserById(id);
}
}
public void addUser(User user) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.insertUser(user);
session.commit();
}
}
public void updateUser(User user) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.updateUser(user);
session.commit();
}
}
public void deleteUser(int id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
userMapper = session.getMapper(UserMapper.class);
userMapper.deleteUser(id);
session.commit();
}
}
}
UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.web.bind.annotation.*;
import java.io.InputStream;
import java.util.List;
@RestController
public class UserController {
private UserService userService;
public UserController() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("mybatis-x-config.xml");
userService = new UserService(inputStream);
}
@GetMapping("/users")
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/users/{id}")
public User getUserById(@PathVariable int id) {
return userService.getUserById(id);
}
@PostMapping("/users")
public void addUser(@RequestBody User user) {
userService.addUser(user);
}
@PutMapping("/users/{id}")
public void updateUser(@PathVariable int id, @RequestBody User user) {
user.setId(id);
userService.updateUser(user);
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id) {
userService.deleteUser(id);
}
}
测试与调试
为了测试 CRUD 操作,可以使用 Postman 或其他 HTTP 客户端工具。这里提供一个简单的测试用例。
测试用例
-
获取所有用户
- URL:
http://localhost:8080/users
- 方法:
GET
- 预期结果: 返回所有用户信息
- URL:
-
获取单个用户
- URL:
http://localhost:8080/users/1
- 方法:
GET
- 预期结果: 返回 ID 为 1 的用户信息
- URL:
-
添加新用户
- URL:
http://localhost:8080/users
- 方法:
POST
- Body:
{"name": "John Doe", "email": "[email protected]"}
- 预期结果: 返回无内容
- URL:
-
更新用户
- URL:
http://localhost:8080/users/1
- 方法:
PUT
- Body:
{"name": "Jane Doe", "email": "[email protected]"}
- 预期结果: 返回无内容
- URL:
- 删除用户
- URL:
http://localhost:8080/users/1
- 方法:
DELETE
- 预期结果: 返回无内容
- URL:
要将 MyBatisX 应用部署到生产环境,可以将其打包为一个 WAR 文件或 JAR 文件,并使用 Tomcat 或其他应用服务器进行运行。
打包为WAR文件
在 pom.xml
文件中添加 Maven 插件 maven-war-plugin
:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<warName>mybatisx-app</warName>
</configuration>
</plugin>
</plugins>
</build>
执行 mvn clean package
命令进行打包。
打包为JAR文件
在 pom.xml
文件中添加 Maven 插件 maven-assembly-plugin
:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<finalName>mybatisx-app</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行 mvn clean package
命令进行打包。
问题1:数据库连接失败
确保数据库连接信息正确无误,并且数据库服务已经启动。
解决方法
检查 mybatis-x-config.xml
文件中的数据库连接信息:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisx"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
确保数据库 mybatisx
已经创建,并且用户 root
有相应的权限。
问题2:SQL映射文件找不到
确保 SQL 映射文件路径正确,并且文件存在于指定位置。
解决方法
检查 mybatis-x-config.xml
文件中的映射文件路径:
<configuration>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
确保 UserMapper.xml
文件存在于 src/main/resources/mapper/
目录下。
为了进一步学习 MyBatisX,可以参考以下资源:
- 官方文档:MyBatisX 官方文档
- 代码示例:MyBatisX 示例代码
- 开发社区:MyBatisX 开发社区
- 书籍:MyBatisX 实战
- 在线课程:慕课网 MyBatisX 课程
通过这些资源,你可以深入了解 MyBatisX 的高级特性和最佳实践,提高你的数据库操作技能。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章