MyBatis系统学习(五)——MyBatis的注解开发

一、MyBatis 注解开发概述

MyBatis 是一个支持自定义 SQL、存储过程和高级映射的持久层框架。除了传统的 XML 方式外,MyBatis 还提供了注解的方式进行 SQL 操作定义。这种注解方式将 SQL 直接写在 Java 接口方法上,简化了开发过程,便于维护和使用。

常见的 MyBatis 注解有:

  • @Select:执行查询 SQL。
  • @Insert:执行插入 SQL。
  • @Update:执行更新 SQL。
  • @Delete:执行删除 SQL。
  • @Results / @Result:定义结果集的映射。
  • @One / @Many:用于处理关联查询(一对一和一对多)。
  • @Param:为参数命名,方便在 SQL 中使用。
  • @Options:配置 SQL 执行选项(如返回自增主键)。

二、基于注解的单表增删改查操作

1. 查询操作 (@Select)

@Select 注解用于执行查询操作,可以直接将查询结果映射为 POJO(Plain Old Java Object)对象或列表。

示例:

public interface UserMapper {
    // 查询所有用户
    @Select("SELECT * FROM user")
    List<User> getAllUsers();

    // 根据 ID 查询用户
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(int id);
}

在此示例中:

  • #{id} 是一个占位符,表示方法参数 id,MyBatis 会自动将参数值传入 SQL 中。
2. 插入操作 (@Insert)

@Insert 用于插入数据,传递的对象属性将自动映射到 SQL 中的字段。

示例:

public interface UserMapper {
    // 插入新用户
    @Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
    int insertUser(User user);
}
3. 更新操作 (@Update)

@Update 用于更新表中的数据,可以根据特定条件(如 ID)更新记录。

示例:

public interface UserMapper {
    // 根据 ID 更新用户信息
    @Update("UPDATE user SET name=#{name}, age=#{age} WHERE id=#{id}")
    int updateUser(User user);
}
4. 删除操作 (@Delete)

@Delete 用于删除数据,通常根据 ID 或其他条件来删除记录。

示例:

public interface UserMapper {
    // 根据 ID 删除用户
    @Delete("DELETE FROM user WHERE id = #{id}")
    int deleteUser(int id);
}

三、基于注解的关联查询

1. 一对一关联查询 (@One)

@One 注解用于处理一对一的关联查询。假设有两张表:user(用户表)和 user_detail(用户详情表),它们通过 user.iduser_detail.user_id 相关联。

示例:

public interface UserMapper {
    // 查询用户及其详情信息
    @Select("SELECT * FROM user WHERE id = #{id}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "age", property = "age"),
        @Result(column = "id", property = "userDetail",
                one = @One(select = "com.example.mapper.UserDetailMapper.getUserDetailByUserId"))
    })
    User getUserWithDetail(int id);
}

public interface UserDetailMapper {
    @Select("SELECT * FROM user_detail WHERE user_id = #{userId}")
    UserDetail getUserDetailByUserId(int userId);
}

在这个例子中,UserMapper 通过 @One 注解来处理 user_detail 的关联查询,UserDetailMapper 用来查询用户的详情信息。

2. 一对多关联查询 (@Many)

@Many 注解用于处理一对多的关联查询。假设用户表 user 和订单表 order 之间是一个用户对应多个订单的关系。

示例:

public interface UserMapper {
    // 查询用户及其订单信息
    @Select("SELECT * FROM user WHERE id = #{id}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "age", property = "age"),
        @Result(column = "id", property = "orders",
                many = @Many(select = "com.example.mapper.OrderMapper.getOrdersByUserId"))
    })
    User getUserWithOrders(int id);
}

public interface OrderMapper {
    @Select("SELECT * FROM `order` WHERE user_id = #{userId}")
    List<Order> getOrdersByUserId(int userId);
}

在此示例中,@Many 用于关联查询用户的订单。OrderMapper 中的 getOrdersByUserId 方法根据用户 ID 查询所有订单。

四、多对多关联查询

多对多关系通常需要第三张关联表。例如,student 表与 course 表之间存在多对多关系,学生可以选修多门课程,课程也可以被多个学生选修。中间表 student_course 用来记录学生和课程的对应关系。

数据库结构:
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);

CREATE TABLE course (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);

CREATE TABLE student_course (
    student_id INT,
    course_id INT,
    FOREIGN KEY (student_id) REFERENCES student(id),
    FOREIGN KEY (course_id) REFERENCES course(id)
);
实现多对多查询:

1. StudentMapper:

public interface StudentMapper {
    // 查询学生及其所选课程
    @Select("SELECT * FROM student WHERE id = #{id}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "id", property = "courses",
                many = @Many(select = "com.example.mapper.CourseMapper.getCoursesByStudentId"))
    })
    Student getStudentWithCourses(int id);
}

2. CourseMapper:

public interface CourseMapper {
    // 根据学生 ID 查询所选课程
    @Select("SELECT course.* FROM course " +
            "JOIN student_course ON course.id = student_course.course_id " +
            "WHERE student_course.student_id = #{studentId}")
    List<Course> getCoursesByStudentId(int studentId);
}

在这个例子中,StudentMapperCourseMapper 协同工作,实现了多对多的查询。通过 student_course 中间表将学生和课程的关系关联起来。

五、其它注解的详细说明

1. @Param 注解

@Param 注解用于为方法中的参数命名,特别是当方法有多个参数时,使用 @Param 可以显式指定参数名,从而避免混淆,提升代码的可读性。

示例:

public interface UserMapper {
    // 根据用户名和年龄查询用户
    @Select("SELECT * FROM user WHERE name = #{name} AND age = #{age}")
    User getUserByNameAndAge(@Param("name") String name, @Param("age") int age);
}

在此示例中,@Param("name")@Param("age") 指定了 SQL 中的参数名称,确保在 SQL 语句中正确映射。

2. @Options 注解

@Options 注解用于配置 SQL 执行时的一些选项。例如,如果表的主键是自增的,可以使用 @Options 来配置插入操作返回生成的主键。

示例:

public interface UserMapper {
    // 插入用户并返回自增主键
    @Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertUser(User user);
}

useGeneratedKeys = true 表示自动生成的主键会被返回并填充到 user 对象的 id 属性中。

六、综合案例

假设我们有一个包含用户、订单、产品的系统。用户可以有多个订单,每个订单包含多个产品(多对多关系)。让我们通过 MyBatis 注解实现该场景。

1. 数据库表结构
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);

CREATE TABLE product (
    id INT PRIMARY KEY AUTO

_INCREMENT,
    name VARCHAR(100)
);

CREATE TABLE `order` (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES user(id)
);

CREATE TABLE order_product (
    order_id INT,
    product_id INT,
    FOREIGN KEY (order_id) REFERENCES `order`(id),
    FOREIGN KEY (product_id) REFERENCES product(id)
);
2. 实体类
public class User {
    private int id;
    private String name;
    private List<Order> orders;  // 用户的订单
}

public class Order {
    private int id;
    private int userId;
    private List<Product> products;  // 订单包含的产品
}

public class Product {
    private int id;
    private String name;
}
3. Mapper 接口

UserMapper:

public interface UserMapper {
    // 查询用户及其订单及产品
    @Select("SELECT * FROM user WHERE id = #{id}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "id", property = "orders",
                many = @Many(select = "com.example.mapper.OrderMapper.getOrdersByUserId"))
    })
    User getUserWithOrdersAndProducts(int id);
}

OrderMapper:

public interface OrderMapper {
    // 根据用户 ID 查询订单
    @Select("SELECT * FROM `order` WHERE user_id = #{userId}")
    @Results({
        @Result(column = "id", property = "id"),
        @Result(column = "user_id", property = "userId"),
        @Result(column = "id", property = "products",
                many = @Many(select = "com.example.mapper.ProductMapper.getProductsByOrderId"))
    })
    List<Order> getOrdersByUserId(int userId);
}

ProductMapper:

public interface ProductMapper {
    // 根据订单 ID 查询产品
    @Select("SELECT product.* FROM product " +
            "JOIN order_product ON product.id = order_product.product_id " +
            "WHERE order_product.order_id = #{orderId}")
    List<Product> getProductsByOrderId(int orderId);
}
4. 综合查询操作

调用 getUserWithOrdersAndProducts 方法,可以获取用户、该用户的所有订单以及每个订单包含的产品。

七、总结

通过 MyBatis 注解开发,开发者可以灵活地定义 SQL 操作,简化 XML 配置文件的使用。单表增删改查、一对一、一对多、多对多等关联查询都可以通过注解方式实现,注解方式具有更好的可读性和维护性。此外,合理使用 @Param@Options 注解,能够提高 SQL 操作的灵活性和易用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值