MyBatis学习(二)

一、代理Dao方式的CRUD操作

1. 代理Dao方式的增删改查

1.1 创建项目

沿用(一)的 Maven 项目,确保依赖和配置文件均已就绪

1.2 UserMapper 接口代码
java 复制代码
package com.qcby.mapper;

import com.qcby.domain.User;
import java.util.List;

public interface UserMapper {

    // 查询所有用户
    public List<User> findAll();

    // 根据ID查询用户
    public User findById(Integer userId);

    // 插入用户
    public void insert(User user);

    // 更新用户
    public void update(User user);

    // 删除用户
    public void delete(Integer userId);

    // 根据用户名模糊查询
    public List<User> findByName(String username);

    // 查询总记录数
    public Integer findByCount();
}
1.3 UserMapper.xml 映射文件

resources/mappers 目录下完善 UserMapper.xml 文件。

java 复制代码
<?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.qcby.mapper.UserMapper">

    <!-- 查询所有 -->
    <select id="findAll" resultType="com.qcby.domain.User">
        select * from user
    </select>

    <!-- 根据ID查询 -->
    <!-- 使用 #{任意变量名} 接收基本类型参数 -->
    <select id="findById" resultType="com.qcby.domain.User" parameterType="int">
        select * from user where id = #{id};
    </select>

    <!-- 保存操作 -->
    <insert id="insert" parameterType="com.qcby.domain.User">
        <!-- 
            selectKey 用于获取插入数据后生成的主键值
            keyProperty: 将查询到的主键值设置到 parameterType 对象的哪个属性
            order: 在 INSERT 语句执行前(BEFORE)后(AFTER)执行
            resultType: 返回的主键类型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id();
        </selectKey>
        insert into user (username,birthday,sex,address) 
        values (#{username},#{birthday},#{sex},#{address})
    </insert>

    <!-- 修改操作 -->
    <update id="update" parameterType="com.qcby.domain.User">
        update user 
        set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} 
        where id = #{id}
    </update>

    <!-- 删除操作 -->
    <delete id="delete" parameterType="Integer">
        delete from user where id = #{id}
    </delete>

    <!-- 模糊查询方式一:推荐,使用 #{...} 拼接,传入参数时需要自己加上 '%' -->
    <!-- 
    <select id="findByName" resultType="com.qcby.domain.User" parameterType="string">
        select * from user where username like #{username}
    </select>
    -->

    <!-- 模糊查询方式二:不推荐,存在SQL注入风险,使用 ${...} 拼接 -->
    <!-- 注意:参数名必须是 value -->
    <select id="findByName" resultType="com.qcby.domain.User" parameterType="string">
        select * from user where username like '%${value}%'
    </select>

    <!-- 查询总记录数 -->
    <select id="findByCount" resultType="int">
        select count(*) from user
    </select>
    
</mapper>
1.4 测试类代码
java 复制代码
package com.qcby.test;

import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
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.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserTest {

    private InputStream in;
    private SqlSession session;
    private UserMapper mapper;

    // 在所有测试方法执行前执行,用于初始化
    @Before
    public void init() throws Exception {
        // 1. 加载主配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2. 创建 SqlSessionFactory 对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 3. 获取 SqlSession 对象
        session = factory.openSession();
        // 4. 获取 Mapper 接口的代理对象
        mapper = session.getMapper(UserMapper.class);
    }

    // 在所有测试方法执行后执行,用于释放资源
    @After
    public void destroy() throws Exception {
        session.close();
        in.close();
    }

    @Test
    public void testFindAll() {
        List<User> list = mapper.findAll();
        for (User user : list) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindById() {
        User user = mapper.findById(1);
        System.out.println(user);
    }

    @Test
    public void testInsert() {
        User user = new User();
        user.setUsername("美美");
        user.setBirthday(new Date());
        user.setSex("女");
        user.setAddress("北京");
        
        mapper.insert(user);
        // 插入操作需要手动提交事务
        session.commit();
        
        System.out.println("插入后生成的主键ID:" + user.getId());
    }

    @Test
    public void testUpdate() {
        User user = mapper.findById(1);
        if (user != null) {
            user.setUsername("小凤");
            mapper.update(user);
            session.commit();
        }
    }

    @Test
    public void testDelete() {
        // 假设删除ID为48的用户
        mapper.delete(48);
        session.commit();
    }

    // 模糊查询示例(对应XML中的方式二)
    @Test
    public void testFindByName() {
        List<User> list = mapper.findByName("王");
        for (User user : list) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindByCount() {
        Integer count = mapper.findByCount();
        System.out.println("总记录数:" + count);
    }
}

二、MyBatis 参数详解

1. parameterType(输入参数类型)

parameterType 用于配置 SQL 语句的参数类型。

**简单数据类型:**如 int, double, String, long 等。

  • 全限定名:java.lang.Integer 等。

  • 别名:MyBatis 提供简写,如 intintegerIntInteger 都可以。

POJO 对象类型: Java 实体类,如 User

**POJO 包装对象类型:**当一个实体类无法满足传参需求时,可以定义一个包装类,包含多个实体作为属性。

2. resultType(输出结果类型)

resultType 用于指定 SQL 语句的返回值类型。

返回简单数据类型:如 int, double, long, String 等。

返回 POJO 数据类型:User,要求 SQL 查询的列名和 POJO 的属性名一致。

**resultMap:**当 SQL 查询字段名和 POJO 属性名不一致时,或需要映射复杂类型(如一对一、一对多)时使用。

resultMap 配置示例

假设 SQL 查询使用了别名,导致字段名与 User 属性不一致。

java 复制代码
<!-- 查询语句中使用了别名 -->
<select id="findUsers" resultMap="userMap">
    select id _id, username _username, birthday _birthday, sex _sex, address _address from user
</select>

<!-- 配置 resultMap 建立映射关系 -->
<!-- 
    id: 唯一标识,被 select 标签的 resultMap 引用
    type: 最终要映射成的 Java 类型
-->
<resultMap id="userMap" type="com.qcby.domain.User">
    <!-- result 标签配置普通属性的映射 -->
    <!--
         property="JavaBean中的属性"
         column="表中的字段"
    -->
    <result property="id" column="_id"/>
    <result property="username" column="_username"/>
    <result property="birthday" column="_birthday"/>
    <result property="sex" column="_sex"/>
    <result property="address" column="_address"/>
</resultMap>
相关推荐
我是发哥哈2 小时前
主流AI视频生成方案商用化能力横向评测
大数据·人工智能·学习·机器学习·chatgpt·音视频
石榴树下的七彩鱼2 小时前
智能抠图 API 多语言接入实战:从零到上线的 Python / Java / PHP / JS 完整教程(附避坑指南)
java·python·php·智能抠图·api接入·石榴智能·shiliuai
楼田莉子2 小时前
CMake学习:CMake语法
c++·后端·学习·软件构建
无限进步_2 小时前
C++ 继承机制完全解析:从基础原理到菱形继承问题
java·开发语言·数据结构·c++·vscode·后端·算法
nashane2 小时前
HarmonyOS 6学习:加密一致性与安全存储——AES GCM排查与SaveButton实践
学习·安全·harmonyos·harmony app
天行健王春城老师2 小时前
从物流路径优化看车间布局设计的底层逻辑
经验分享
SamDeepThinking2 小时前
适合中小型企业的出口入口网关微服务
java·后端·架构
不知名的忻2 小时前
并查集(QuickUnion)
java·数据结构·算法·并查集
java1234_小锋2 小时前
MyBatis中XML映射有哪些标签?
xml·tomcat·mybatis