MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射,几乎消除了 JDBC 代码的手动编写,通过简单的 XML 或注解配置即可完成数据库操作,MyBatis 关联数据库的核心在于其配置文件、映射接口以及动态 SQL 机制,下面从环境搭建、核心配置、关联方式及实际应用场景等方面详细说明其关联数据库的过程。
环境搭建与核心配置
MyBatis 关联数据库首先需要正确配置数据库连接信息,这主要在 mybatis-config.xml
配置文件中完成,该文件是 MyBatis 的全局配置文件,包含数据库连接池、事务管理器、映射器位置等核心配置。
数据库连接配置
在 mybatis-config.xml
中,通过 <environments>
标签配置数据库环境,每个环境包含 transactionManager
(事务管理器)和 dataSource
(数据源)。
<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/mydb?useSSL=false&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> <property name="poolMaximumActive" value="10"/> </dataSource> </environment> </environments>
dataSource
的 type
可选 UNPOOLED
(无连接池)、POOLED
(连接池)或 JNDI
(Java 命名目录接口),开发中常用 POOLED
提升性能。
映射器注册
MyBatis 通过映射器(Mapper)将 SQL 语句与 Java 方法绑定,需在 mybatis-config.xml
中通过 <mappers>
标签注册映射文件或接口:
<mappers> <mapper resource="com/example/mapper/UserMapper.xml"/> <mapper class="com.example.mapper.UserMapper"/> </mappers>
映射文件(如 UserMapper.xml
)定义 SQL 语句及结果映射,而映射接口(如 UserMapper
)通过注解或 XML 绑定 SQL。
映射文件与 SQL 关联
映射文件是 MyBatis 关联数据库的核心,它定义了 SQL 语句、参数映射和结果集处理。
基础 CRUD 操作
以 User
表为例,假设表结构包含 id
(主键)、name
、age
字段,映射文件中的 select
、insert
、update
、delete
标签分别对应增删改查操作:
<mapper namespace="com.example.mapper.UserMapper"> <!-- 查询用户:根据 id 查询,返回 User 对象 --> <select id="selectUserById" resultType="com.example.entity.User"> SELECT id, name, age FROM user WHERE id = #{id} </select> <!-- 插入用户:参数为 User 对象,useGeneratedKeys 返回主键 --> <insert id="insertUser" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (name, age) VALUES (#{name}, #{age}) </insert> <!-- 更新用户:根据 id 更新 name 和 age --> <update id="updateUser" parameterType="com.example.entity.User"> UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id} </update> <!-- 删除用户:根据 id 删除 --> <delete id="deleteUserById" parameterType="int"> DELETE FROM user WHERE id = #{id} </delete> </mapper>
namespace
:必须与映射接口的全限定名一致,用于绑定接口方法。resultType
:指定 SQL 返回结果的对象类型,如com.example.entity.User
。parameterType
:指定传入参数的类型,可以是基本类型(如int
)或对象(如User
)。- MyBatis 的参数占位符,会预编译处理,防止 SQL 注入。
动态 SQL 与多表关联
实际开发中常需动态拼接 SQL 或关联多表,MyBatis 通过 <if>
、<where>
、<foreach>
等标签实现动态 SQL,通过 <resultMap>
实现多表关联。
动态 SQL 示例
根据条件查询用户,可能涉及 name
和 age
的模糊匹配:
<select id="selectUsersByCondition" resultType="com.example.entity.User"> SELECT id, name, age FROM user <where> <if test="name != null and name != ''"> AND name LIKE CONCAT('%', #{name}, '%') </if> <if test="age != null"> AND age = #{age} </if> </where> </select>
<where>
标签会自动处理 AND
的拼接问题,避免 SQL 语法错误。
多表关联(一对一、一对多)
假设 User
表与 Order
表是一对多关系(一个用户有多个订单),需通过 <resultMap>
定义结果映射:
(1)定义 ResultMap
<resultMap id="userOrderMap" type="com.example.entity.User"> <id property="id" column="user_id"/> <result property="name" column="user_name"/> <result property="age" column="user_age"/> <!-- 一对多关联:collection 标签关联 List<Order> --> <collection property="orders" ofType="com.example.entity.Order"> <id property="id" column="order_id"/> <result property="orderName" column="order_name"/> <result property="price" column="order_price"/> </collection> </resultMap>
(2)编写关联查询 SQL
<select id="selectUserWithOrders" resultMap="userOrderMap"> SELECT u.id as user_id, u.name as user_name, u.age as user_age, o.id as order_id, o.name as order_name, o.price as order_price FROM user u LEFT JOIN `order` o ON u.id = o.user_id WHERE u.id = #{userId} </select>
<collection>
:处理一对多关联,property
是 User 实体中的 orders 属性,ofType
指定集合中元素的类型(Order)。<association>
:处理一对一关联(如 User 与 Address),用法与<collection>
类似,但对应单个对象。
通过注解关联数据库
除 XML 外,MyBatis 支持通过注解在映射接口中直接定义 SQL,适合简单场景:
@Mapper public interface UserMapper { @Select("SELECT id, name, age FROM user WHERE id = #{id}") User selectUserById(int id); @Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})") @Options(useGeneratedKeys = true, keyProperty = "id") // 返回主键 void insertUser(User user); @Select("SELECT u.*, o.id as order_id, o.name as order_name " + "FROM user u LEFT JOIN `order` o ON u.id = o.user_id " + "WHERE u.id = #{userId}") @Results({ // 定义结果映射,替代 ResultMap @Result(property = "id", column = "id"), @Result(property = "name", column = "name"), @Result(property = "age", column = "age"), @Result(property = "orders", javaType = List.class, column = "id", many = @Many(select = "com.example.mapper.OrderMapper.selectByUserId")) // 延迟加载 }) User selectUserWithOrders(int userId); }
@Mapper
:标记接口为 MyBatis 映射器。@Select
、@Insert
等注解直接定义 SQL,简单场景下无需 XML 文件。@Results
和@Result
替代 XML 中的resultMap
,@Many
和@One
处理多表关联。
执行流程总结
MyBatis 关联数据库的执行流程可概括为:
- 加载配置:读取
mybatis-config.xml
配置文件,初始化SqlSessionFactory
(会话工厂)。 - 创建会话:通过
SqlSessionFactory
创建SqlSession
(会话对象),相当于 JDBC 中的Connection
。 - 获取映射器:通过
SqlSession.getMapper(UserMapper.class)
获取映射接口实例。 - 执行 SQL:调用映射接口方法(如
selectUserById
),MyBatis 底层根据注解或 XML 生成 SQL,通过Executor
执行并返回结果。 - 结果映射:将 JDBC 返回的
ResultSet
通过TypeHandler
转换为 Java 对象,完成数据库与对象的关联。
相关问答 FAQs
Q1:MyBatis 中 和 的区别是什么?
A: 是预编译处理,会替换为 ,防止 SQL 注入,适用于参数传递(如 WHERE id = #{id}
); 是字符串替换,直接拼接 SQL,存在 SQL 注入风险,适用于动态表名或列名(如 ORDER BY ${columnName}
),开发中应优先使用 。
Q2:MyBatis 如何实现延迟加载(懒加载)?
A:延迟加载指关联对象在真正使用时才查询数据库,通过 lazyLoadingEnabled
配置和 @Result
的 select
属性实现,在 mybatis-config.xml
中开启延迟加载:
<settings> <setting name="lazyLoadingEnabled" value="true"/> </settings>
在 resultMap
中通过 select
属性指定关联查询的 SQL(如 @Many(select = "selectByUserId")
),当访问 User 对象的 orders
属性时,才会触发 Order 表的查询。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复