自学内容网 自学内容网

【Java_EE】Day05 MyBatis注解开发

Day05 MyBatis注解开发

基于注解的单表增删改查

除了前四节我们使用XML的映射方式进行开发,其实我们更常用的方式是通过Mybatis的注解实现POJO实体对象和数据表,一般我们直接把他写在接口上。这样的好处在于相对来讲更简单,而且不会增加开销。MyBatis提供了@Select@Insert@Update@Delete以及@Param等用于增删改查,以及传递参数的常用注解。

@Select注解

@Select注解用于映射查询语句,下面通过根据员工id查找员工信息的案例来演示一下如何使用注解进行开发。

  1. mybatis数据库中创建名称为tb_worker的数据表,同时预先插入三条测试数据,具体语句如下所示:
USE mybatis;
# 创建一个名称为tb_worker的表
CREATE TABLE tb_worker(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32),
    age INT,
    sex VARCHAR(8),
    worker_id INT UNIQUE
);
# 插入3条数据
INSERT INTO tb_worker (name,age,sex,worker_id)
VALUES ('张三', 32, '女', 1001),
       ('李四', 29, '男', 1002),
       ('王五', 26, '男', 1003);
  1. 在项目pojo包下创建持久化实体类Worker.java,并在其中定义表中所有属性以及getter/setter方法、toString()方法:
package com.itheima.pojo;

/**
 * 员工持久化类
 * @author Zhang
 */
public class Worker {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    // 这里为了符合java命名规范,我们使用小驼峰命名法
    // 但是要记住,我们永久类中的属性名必须和数据库中的字段名保持一致
    // 所以我们要在一会给他一个别名
    private String workerId;

    @Override
    public String toString() {
        return "Worker{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", workerId='" + workerId + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getWorkerId() {
        return workerId;
    }

    public void setWorkerId(String workerId) {
        this.workerId = workerId;
    }
}

  1. 在项目的src/main/java包下创建一个com.itheima.dao包,并在该包下创建WorkerMapper接口,用于编写@Select注解映射的select查询方法。代码如下:
package com.itheima.dao;

import com.itheima.pojo.Worker;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface WorkerMapper {
    // 当程序调用selectWorker方法时, 就会自动执行@Select注解中的语句了
    @Select("select * from mybatis.tb_worker where id=#{id}")
    Worker selectWorker (int id);
}

  1. 在核心配置文件mybatis-config.xml中的<mappers>元素下引入WorkerMapper接口,将WorkerMapper.java接口加载到核心配置文件中,具体代码添加如下:
        <mapper class="com.itheima.dao.WorkerMapper"/>
  1. 为了验证上述配置,在测试类MybatisTest中编写测试方法findWorkerByIdTest(),具体代码如下:
    @Test
    public void findWorkerByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        WorkerMapper mapper = session.getMapper(WorkerMapper.class);
        // 使用WorkerMapper对象查询id为1的员工信息
        Worker worker = mapper.selectWorker(1);
        System.out.println(worker.toString());
        session.close();
    }
  1. 运行结果应该是如下:
2024-10-08 23:56:08,084 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorker] - ==>  Preparing: SELECT * FROM mybatis.tb_worker WHERE id=?
2024-10-08 23:56:08,116 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorker] - ==> Parameters: 1(Integer)
2024-10-08 23:56:08,135 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorker] - <==      Total: 1
Worker{id=1, name='张三', age=32, sex='女', worker_id='1001'}

@Insert注解

@Insert注解用于映射插入语句,下面通过实现员工信息的插入案例来演示,具体步骤如下:

  1. WorkerMapper接口中添加向tb_worker数据表插入数据的方法insertWorker(),并在方法上添加@Insert注解,具体实现代码如下:
@Insert("INSERT INTO mybatis.tb_worker(name,sex,age,worker_id) " +
            "VALUES(#{name},#{sex},#{age},#{worker_id})")
    int insertWorker(Worker worker);
  1. 为了验证上述配置,我们在测试类中编写测试方法insertWorkerTest(),具体代码如下:
    @Test
    public void insertWorkerTest() {
        SqlSession session = MyBatisUtils.getSession();
        Worker worker = new Worker();
        worker.setId(4);
        worker.setName("赵六");
        worker.setAge(36);
        worker.setSex("女");
        worker.setWorker_id("1004");
        WorkerMapper mapper = session.getMapper(WorkerMapper.class);
        // 插入员工信息
        int result = mapper.insertWorker(worker);
        if (result > 0) {
            System.out.println("插入成功");
        } else {
            System.out.println("插入失败");
        }
        System.out.println(worker.toString());
        // 提交当前会话,将所有待处理的变更持久化到数据库中
        session.commit();
        session.close();
    }
  1. 插入成功应该会在控制台返回如下内容:
2024-10-09 00:09:20,309 [main] DEBUG [com.itheima.dao.WorkerMapper.insertWorker] - ==>  Preparing: INSERT INTO mybatis.tb_worker(name,sex,age,worker_id) VALUES(?,?,?,?)
2024-10-09 00:09:20,338 [main] DEBUG [com.itheima.dao.WorkerMapper.insertWorker] - ==> Parameters: 赵六(String),(String), 36(Integer), 1004(String)
2024-10-09 00:09:20,340 [main] DEBUG [com.itheima.dao.WorkerMapper.insertWorker] - <==    Updates: 1
插入成功
Worker{id=4, name='赵六', age=36, sex='女', worker_id='1004'}

@Update注解

@Update注解用于映射更新语句,下面通过实现员工信息的修改案例来说一说这个注解该如何使用。

  1. WorkerMapper接口中添加更新tb_worker表中数据的方法,并在方法上添加@Update注解,具体代码如下:
@Update("UPDATE mybatis.tb_worker SET name=#{name} WHERE id=#{id}")
    int updateWorker(Worker worker);
  1. 为了验证上述配置,在测试类MyBatisTest中添加测试方法updateWorkerTest()方法,具体代码如下:
    @Test
    public void updateWorkerTest() {
        SqlSession session = MyBatisUtils.getSession();
        Worker worker = new Worker();
        worker.setId(4);
        worker.setName("李华");
        worker.setAge(28);
        WorkerMapper mapper = session.getMapper(WorkerMapper.class);
        // 更新员工信息
        int result = mapper.updateWorker(worker);
        if (result > 0) {
            System.out.println("更新成功");
            System.out.println("成功更新"+result+"条数据!");
        } else {
            System.out.println("更新失败");
        }
        System.out.println(worker.toString());
        // 提交事务
        session.commit();
        // 关闭session
        session.close();
    }
  1. 输出结果应该是这样的:
2024-10-09 02:00:51,237 [main] DEBUG [com.itheima.dao.WorkerMapper.updateWorker] - ==>  Preparing: UPDATE mybatis.tb_worker SET name=? WHERE id=?
2024-10-09 02:00:51,262 [main] DEBUG [com.itheima.dao.WorkerMapper.updateWorker] - ==> Parameters: 李华(String), 4(Integer)
2024-10-09 02:00:51,268 [main] DEBUG [com.itheima.dao.WorkerMapper.updateWorker] - <==    Updates: 1
更新成功
成功更新1条数据!
Worker{id=4, name='李华', age=28, sex='null', worker_id='null'}

@Delete注解

@Delete注解用于映射删除语句,实现数据库信息的删除,为具体演示,我们通过实现员工信息删除的案例如下:

  1. WorkerMapper接口中添加删除数据库中数据的方法,并在方法上添加@Delete注解标注的deleteWorker()方法时,@Delete注解中映射的删除语句将会被执行:
@Delete("DELETE FROM mybatis.tb_worker WHERE id=#{id}")
    int deleteWorker(int id);
  1. 为了验证上述配置,我们在测试类中编写方法deleteWorkerTest()方法,具体代码如下:
@Test
    public void deleteWorkerTest() {
        SqlSession session = MyBatisUtils.getSession();
        WorkerMapper mapper = session.getMapper(WorkerMapper.class);
        // 删除员工信息
        int result = mapper.deleteWorker(4);
        if (result > 0) {
            System.out.println("删除成功");
            System.out.println("成功删除"+result+"条数据!");
        } else {
            System.out.println("删除失败");
        }
        // 提交事务
        session.commit();
        //关闭session
        session.close();
    }
  1. 输出结果应该是这样的:
2024-10-09 02:18:22,753 [main] DEBUG [com.itheima.dao.WorkerMapper.deleteWorker] - ==>  Preparing: DELETE FROM mybatis.tb_worker WHERE id=?
2024-10-09 02:18:22,783 [main] DEBUG [com.itheima.dao.WorkerMapper.deleteWorker] - ==> Parameters: 4(Integer)
2024-10-09 02:18:22,785 [main] DEBUG [com.itheima.dao.WorkerMapper.deleteWorker] - <==    Updates: 1
删除成功
成功删除1条数据!

@Param注解

@Param注解的功能是指定SQL语句中的参数,通常用于SQL语句中参数比较多的情况。下面通过根据员工的id和姓名查询员工信息的案例来具体演示一下:

  1. WorkerMapper接口中添加多条件查询的方法,具体代码如下:
@Select("SELECT * FROM mybatis.tb_worker WHERE id=#{param01} AND name=#{param02}")
    Worker selectWorkerByWorkerId(@Param("param01") int id, @Param("param02") String name);
  1. 编写测试方法selectWorkerByWorkerIdTest(),具体代码如下:
@Test
    public void selectWorkerByWorkerIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        WorkerMapper mapper = session.getMapper(WorkerMapper.class);
        // 查询id为3且姓名为王五的员工信息
        Worker worker = mapper.selectWorkerByWorkerId(3, "王五");
        System.out.println(worker.toString());
        session.close();
    }
  1. 正确输出结果应如下:
2024-10-09 02:28:12,311 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorkerByWorkerId] - ==>  Preparing: SELECT * FROM mybatis.tb_worker WHERE id=? AND name=?
2024-10-09 02:28:12,336 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorkerByWorkerId] - ==> Parameters: 3(Integer), 王五(String)
2024-10-09 02:28:12,351 [main] DEBUG [com.itheima.dao.WorkerMapper.selectWorkerByWorkerId] - <==      Total: 1
Worker{id=3, name='王五', age=26, sex='男', worker_id='1003'}

基于注解的关联查询

MyBatis提供了@Results、@Result、@One和@Many等注解用于表之间的关联查询。

一对一查询

MyBatis中使用@One注解实现数据表的一对一关联查询,一下通过已有的tb_idcardtb_person数据表为例,感受基于@One注解实现tb_person数据表之间的一对一关联查询。

  1. 在项目的com.itheima.dao包下创建IdCardMapper接口,并再该接口中编写一个selectIdCardById()方法,用于通过id查询人员对应的身份证信息,具体代码如下:
package com.itheima.dao;

import com.itheima.pojo.IdCard;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface IdCardMapper {
    @Select("select * from mybatis.tb_idcard where id = #{id}")
    IdCard findIdCardById(int id);
}

  1. 在项目的com.itheima.dao包下创建PersonMapper接口,再改接口中编写selectPersonById()方法,通过id查询人员信息。具体代码如下:
package com.itheima.dao;

import com.itheima.pojo.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface PersonMapper {
    @Select("select * from mybatis.tb_person where id = #{id}")
    // 配置结果映射,将数据库查询结果映射到实体类属性
    @Results({@Result(
            // 指定表中的列名,数据库中的名字
            column = "card_id",
            // 指定POJO类中的属性名,属性名,如果起了别名要匹配POJO的属性名
            property = "card",
            // 配置一对一关联关系,指定关联属性card的值是通过哪个方法获得的
            one = @One(select = "com.itheima.dao.IdCardMapper.selectIdCardById")
    )})
    Person selectPersonById(int id);
}

  1. 在核心配置文件中引入这两个Mapper接口,具体引入代码如下:
<mapper class="com.itheima.dao.PersonMapper"/>
<mapper class="com.itheima.dao.IdCardMapper"/>
  1. 为了验证上述配置,我们在测试类中编写测试方法selectPersonByIdTest(),具体代码如下:
@Test
    public void selectPersonByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        PersonMapper mapper = session.getMapper(PersonMapper.class);
        // 查询id为1的人员信息
        Person person = mapper.selectPersonById(1);
        System.out.println(person.toString());
        session.close();
    }
  1. 正确结果应该输出如下信息:
2024-10-09 15:51:19,147 [main] DEBUG [com.itheima.dao.PersonMapper.selectPersonById] - ==>  Preparing: select * from mybatis.tb_person where id = ?
2024-10-09 15:51:19,175 [main] DEBUG [com.itheima.dao.PersonMapper.selectPersonById] - ==> Parameters: 1(Integer)
2024-10-09 15:51:19,226 [main] DEBUG [com.itheima.dao.PersonMapper.selectPersonById] - <==      Total: 1
2024-10-09 15:51:19,228 [main] DEBUG [com.itheima.dao.IdCardMapper.selectIdCardById] - ==>  Preparing: select * from mybatis.tb_idcard where id = ?
2024-10-09 15:51:19,228 [main] DEBUG [com.itheima.dao.IdCardMapper.selectIdCardById] - ==> Parameters: 1(Integer)
2024-10-09 15:51:19,230 [main] DEBUG [com.itheima.dao.IdCardMapper.selectIdCardById] - <==      Total: 1
Person{id=1, name='Rose', age=22, sex='女', card=IdCard{id=1, code='152221198711020624'}}

一对多查询

MyBatis使用@Many注解实现数据表的一对多关联查询,以tb_usertb_orders数据表为例,讲解基于@Many注解配置实现tb_usertb_orders数据表之间的一对多关联查询。

  1. 在项目的com.itheima.dao包下创建OrdersMapper接口,并编写selectOrdersByUserId()方法,通过user_id查询用户对应订单信息,具体代码如下:
package com.itheima.dao;

import com.itheima.pojo.Orders;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author Zhang
 */
public interface OrdersMapper {
    @Select("select * from mybatis.tb_orders where user_id = #{id}")
    // id属性表示是否为主键, 主键为true, 否则不用写或为false
    @Results({@Result(id = true, column = "id", property = "id"),
            @Result(column = "number", property = "number")
    })
    List<Orders> selectOrdersByUserId(int user_id);
}
  1. 在项目的com.itheima.dao包下创建UsersMapper接口,并编写selectUserById()方法,通过id查询用户信息,具体代码如下:
package com.itheima.dao;

import com.itheima.pojo.Users;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface UsersMapper {
    @Select("select * from mybatis.tb_user where id = #{id}")
    @Results({@Result(id = true, column = "id", property = "id"), 
            @Result(column = "username", property = "username"),
            @Result(column = "address", property = "address"),
            @Result(column = "id", property = "ordersList", 
                    many = @Many(select = "com.itheima.dao.OrdersMapper.selectOrdersByUserId"))
    })
    Users selectUserById(int id);
}

  1. 将这两个Mapper引入到核心加载配置文件中,代码如下:
        <mapper class="com.itheima.dao.OrdersMapper"/>
        <mapper class="com.itheima.dao.UsersMapper"/>
  1. 为了验证上述配置,我们在测试类中添加selectUserByIdTest()方法,代码如下:
@Test
    public void selectUserByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        UsersMapper mapper = session.getMapper(UsersMapper.class);
        // 查询id为1的人的信息
        Users users = mapper.selectUserById(1);
        System.out.println(users.toString());
        session.close();
    }
  1. 正确的查询结果应如下:
2024-10-10 05:01:32,472 [main] DEBUG [com.itheima.dao.UsersMapper.selectUserById] - ==>  Preparing: select * from mybatis.tb_user where id = ?
2024-10-10 05:01:32,501 [main] DEBUG [com.itheima.dao.UsersMapper.selectUserById] - ==> Parameters: 1(Integer)
2024-10-10 05:01:32,563 [main] DEBUG [com.itheima.dao.UsersMapper.selectUserById] - <==      Total: 1
2024-10-10 05:01:32,565 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersByUserId] - ==>  Preparing: select * from mybatis.tb_orders where user_id = ?
2024-10-10 05:01:32,565 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersByUserId] - ==> Parameters: 1(Integer)
2024-10-10 05:01:32,571 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersByUserId] - <==      Total: 2
Users{id=1, username='小明', address='北京', ordersList=[Orders{id=1, number='1000011', productList=null}, Orders{id=2, number='1000012', productList=null}]}

多对多查询

在数据库中,表与表之间的多对多关联关系通常使用一个中间表来维护,以订单表tb_orders和商品表tb_product为例,这两个表之间的关联关系使用了一个中间表tb_ordersitem来维护,订单表tb_orders和商品表tb_product都与中间表tb_ordersitem形成了一对多关系。

下面基于Orders类、Product类,以订单表tb_orders、商品表tb_product和中间表tb_ordersitem为例,详细讲解tb_orderstb_product数据表之间基于注解的多对多关联查询,具体步骤如下:

  1. 在项目的com.itheima.dao包下创建ProductMapper接口,在该接口编写selectProductByOrdersId()方法,通过user_id查询用户对应的订单信息。ProductMapper接口的具体代码如下所示:
package com.itheima.dao;

import com.itheima.pojo.Product;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author Zhang
 */
public interface ProductMapper {
    @Select("SELECT * " +
            "FROM mybatis.tb_product " +
            "WHERE id IN (" +
            "SELECT mybatis.tb_ordersitem.product_id " +
            "FROM tb_ordersitem " +
            "WHERE orders_id = #{id})"
    )
    List<Product> selectProductByOrdersId(int orders_id);
}

  1. 在项目的com.itheima.dao包下OrdersMapper接口里,添加selectOrdersById()方法,该方法用于通过id查询订单信息。selectOrdersById()方法具体代码如下:
@Select("select * from mybatis.tb_orders where id = #{id}")
    @Results({@Result(id = true, column = "id", property = "id"), 
            @Result(column = "number", property = "number"), 
            @Result(column = "id", property = "productList", 
                    many = @Many(select = "com.itheima.dao.ProductMapper.selectProductByOrdersId")
            )})
    Orders selectOrdersById(int id);
  1. 在核心配置文件中引入ProductMapper接口,由于OrdersMapper已经引入过了,所以无需再次引入,具体代码如下:
<mapper class="com.itheima.dao.ProductMapper"/>
  1. 为了验证上述配置,我们在测试类中编写selectOrdersByIdTest()方法,具体代码如下:
@Test
    public void selectOrdersByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        OrdersMapper mapper = session.getMapper(OrdersMapper.class);
        // 查询id为3的订单信息
        Orders orders = mapper.selectOrdersById(3);
        System.out.println(orders.toString());
        session.close();
    }
  1. 查询结果应如下所示:
2024-10-10 05:37:53,947 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersById] - ==>  Preparing: select * from mybatis.tb_orders where id = ?
2024-10-10 05:37:53,976 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersById] - ==> Parameters: 3(Integer)
2024-10-10 05:37:54,024 [main] DEBUG [com.itheima.dao.OrdersMapper.selectOrdersById] - <==      Total: 1
2024-10-10 05:37:54,026 [main] DEBUG [com.itheima.dao.ProductMapper.selectProductByOrdersId] - ==>  Preparing: SELECT * FROM mybatis.tb_product WHERE id IN (SELECT mybatis.tb_ordersitem.product_id FROM tb_ordersitem WHERE orders_id = ?)
2024-10-10 05:37:54,027 [main] DEBUG [com.itheima.dao.ProductMapper.selectProductByOrdersId] - ==> Parameters: 3(Integer)
2024-10-10 05:37:54,035 [main] DEBUG [com.itheima.dao.ProductMapper.selectProductByOrdersId] - <==      Total: 1
Orders{id=3, number='1000013', productList=[Product{id=3, name='SSM框架整合实践入门', price=50.0, orders=null}]}

案例:基于MyBatis注解的学生管理程序

现在有一个学生表s_student和一个班级表c_class,其中,班级表c_class和学生表s_student是一对多的关系。学生表s_student和班级表c_class分别如下所示:

学生id(id)学生姓名(name)学生年龄(age)所属班级(cid)
1张三181
2李四182
3王五192
4赵六201
班级id(id)班级名称(classname)
1一班
2二班

需求如下,请使用MyBatis注解完成以下要求:

  1. MyBatis注解实现查询操作。根据上表在数据库分别创建一个学生表s_student和一个班级表c_class,并查询id为2的学生信息。

  2. MyBatis注解实现修改操作。将id为4的学生姓名修改为李雷,年龄修改为21。

  3. MyBatis注解实现一对多查询。查询出二班所有学生的信息。

代码实现:

需求如下,请使用MyBatis注解完成以下要求:

  1. MyBatis注解实现查询操作。根据上表在数据库分别创建一个学生表s_student和一个班级表c_class,并查询id为2的学生信息。
USE mybatis;
# 根据上表在数据库分别创建一个学生表`s_student`和一个班级表`c_class`
CREATE TABLE s_student(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32),
    age INT,
    cid INT
);

CREATE TABLE c_class(
    id INT PRIMARY KEY AUTO_INCREMENT,
    classname VARCHAR(32)
);

# 插入数据
INSERT INTO s_student VALUES ('1', '张三', 18, '1'),
                             ('2', '李四', 18, '2'),
                             ('3', '王五', 19, '2'),
                             ('4', '赵六', 20, '1');

INSERT INTO c_class VALUES ('1', '一班'),
                           ('2', '二班');

com.itheima.pojo包下创建持久化类SStudentCClass,并添加数据库所有属性以及getter/settertoString()方法。

SStudent.java

package com.itheima.pojo;

/**
 * @author Zhang
 */
public class SStudent {
    private Integer id;
    private String name;
    private Integer age;
    private Integer cid;

    @Override
    public String toString() {
        return "SStudent{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", cid=" + cid +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }
}

CClass.java

package com.itheima.pojo;

/**
 * @author Zhang
 */
public class CClass {
    private Integer id;
    private String classname;

    @Override
    public String toString() {
        return "CClass{" +
                "id=" + id +
                ", classname='" + classname + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getClassname() {
        return classname;
    }

    public void setClassname(String classname) {
        this.classname = classname;
    }
}

设计DAO层接口,分别在com.itheima.dao下创建SStudentMapper,并在其中创建findStudentById()方法,为了后续使用,同时创建CClassMapper接口,代码如下:

SStudentMapper.java

package com.itheima.dao;

import com.itheima.pojo.SStudent;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface SStudentMapper {
    @Select("SELECT * FROM mybatis.s_student WHERE id = #{id}")
    SStudent findStudentById(int id);
}

CClassMapper.java

package com.itheima.dao;

/**
 * @author Zhang
 */
public interface CClassMapper {
}

在核心配置文件中引入这两个Mapper,代码如下:

<mapper class="com.itheima.dao.SStudentMapper"/>
        <mapper class="com.itheima.dao.CClassMapper"/>

为了检查上述代码可行性,我们在测试类中编写findStudentByIdTest()方法,如下代码:

@Test
    public void findStudentByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        SStudentMapper mapper = session.getMapper(SStudentMapper.class);
        // 查询id为2的学生信息
        SStudent student = mapper.findStudentById(2);
        System.out.println(student.toString());
        session.close();
    }

输出结果应该如下:

2024-10-10 06:32:23,491 [main] DEBUG [com.itheima.dao.SStudentMapper.findStudentById] - ==>  Preparing: SELECT * FROM mybatis.s_student WHERE id = ?
2024-10-10 06:32:23,523 [main] DEBUG [com.itheima.dao.SStudentMapper.findStudentById] - ==> Parameters: 2(Integer)
2024-10-10 06:32:23,543 [main] DEBUG [com.itheima.dao.SStudentMapper.findStudentById] - <==      Total: 1
SStudent{id=2, name='李四', age=18, cid=2}
  1. MyBatis注解实现修改操作。将id为4的学生姓名修改为李雷,年龄修改为21。

SStudentMapper接口中定义一个updateStudentById()方法,代码如下:

    @Update("UPDATE mybatis.s_student " +
            "SET name = #{name}, age = #{age} " +
            "WHERE id = #{id}")
    int updateStudentById(SStudent student);

为了验证上述配置是否生效,我们在测试类中编写updateStudentByIdTest()测试方法,代码如下:

    @Test
    public void updateStudentByIdTest() {
        SqlSession session = MyBatisUtils.getSession();
        SStudentMapper mapper = session.getMapper(SStudentMapper.class);
        // 更新id为4的学生信息
        SStudent student = new SStudent();
        student.setId(4);
        student.setName("李雷");
        student.setAge(21);
        int result = mapper.updateStudentById(student);
        if (result > 0) {
            System.out.println("更新成功");
        } else {
            System.out.println("更新失败");
        }
        System.out.println(student.toString());
        session.commit();
        session.close();
    }

结果应当如下:

2024-10-10 06:43:47,484 [main] DEBUG [com.itheima.dao.SStudentMapper.updateStudentById] - ==>  Preparing: UPDATE mybatis.s_student SET name = ?, age = ? WHERE id = ?
2024-10-10 06:43:47,512 [main] DEBUG [com.itheima.dao.SStudentMapper.updateStudentById] - ==> Parameters: 李雷(String), 21(Integer), 4(Integer)
2024-10-10 06:43:47,513 [main] DEBUG [com.itheima.dao.SStudentMapper.updateStudentById] - <==    Updates: 1
更新成功
SStudent{id=4, name='李雷', age=21, cid=null}
  1. MyBatis注解实现一对多查询。查询出二班所有学生的信息。

要查询二班所有学生信息,需要让s_student表中的c_id去链接c_class表中的id项。

我们先在SStudentMapper接口中写一个selectStudentByCid()方法,代码如下:

@Select("SELECT * FROM mybatis.s_student WHERE cid = #{cid}")
    @Results({
            @Result(id = true, column = "id", property = "id"),
            @Result(column = "name", property = "name"),
            @Result(column = "age", property = "age")
    })
    List<SStudent> selectStudentByCid(int cid);

然后在CClassMapper接口中写一个selectStudentByClassname()方法,代码如下:

package com.itheima.dao;

import com.itheima.pojo.CClass;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

/**
 * @author Zhang
 */
public interface CClassMapper {
    @Select("SELECT * FROM mybatis.c_class WHERE classname = #{classname}")
    @Results({
            @Result(column = "classname", property = "classname"),
            @Result(column = "id", property = "sStudentList",
                    many = @Many(select = "com.itheima.dao.SStudentMapper.selectStudentByCid"))
    })
    CClass selectStudentByClassname(String classname);
}

随后在CClass的POJO持久化类中增加List<SStudent>以方便操作接收到的SStudent表中的数据,完整CClass.java内容如下:

package com.itheima.pojo;

import java.util.List;

/**
 * @author Zhang
 */
public class CClass {
    private Integer id;
    private String classname;
    private List<SStudent> sStudentList;

    @Override
    public String toString() {
        return "CClass{" +
                "id=" + id +
                ", classname='" + classname + '\'' +
                ", sStudentList=" + sStudentList +
                '}';
    }

    public List<SStudent> getsStudentList() {
        return sStudentList;
    }

    public void setsStudentList(List<SStudent> sStudentList) {
        this.sStudentList = sStudentList;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getClassname() {
        return classname;
    }

    public void setClassname(String classname) {
        this.classname = classname;
    }
}

为了检验我们上述方法是否可以实现需求,我们在测试类中增加selectStudentByClassnameTest()方法,代码如下:

    @Test
    public void selectStudentByClassnameTest() {
        SqlSession session = MyBatisUtils.getSession();
        CClassMapper mapper = session.getMapper(CClassMapper.class);
        // 查询班级名为"二班"的学生信息
        CClass cClass = mapper.selectStudentByClassname("二班");
        System.out.println(cClass.toString());
        session.close();
    }

输出结果应该是这样的:

2024-10-10 07:23:44,138 [main] DEBUG [com.itheima.dao.CClassMapper.selectStudentByClassname] - ==>  Preparing: SELECT * FROM mybatis.c_class WHERE classname = ?
2024-10-10 07:23:44,169 [main] DEBUG [com.itheima.dao.CClassMapper.selectStudentByClassname] - ==> Parameters: 二班(String)
2024-10-10 07:23:44,219 [main] DEBUG [com.itheima.dao.CClassMapper.selectStudentByClassname] - <==      Total: 1
2024-10-10 07:23:44,221 [main] DEBUG [com.itheima.dao.SStudentMapper.selectStudentByCid] - ==>  Preparing: SELECT * FROM mybatis.s_student WHERE cid = ?
2024-10-10 07:23:44,221 [main] DEBUG [com.itheima.dao.SStudentMapper.selectStudentByCid] - ==> Parameters: 2(Integer)
2024-10-10 07:23:44,223 [main] DEBUG [com.itheima.dao.SStudentMapper.selectStudentByCid] - <==      Total: 2
CClass{id=null, classname='二班', sStudentList=[SStudent{id=2, name='李四', age=18, cid=2}, SStudent{id=3, name='王五', age=19, cid=2}]}

本章小结

本章主要讲解了MyBatis的注解开发。首先介绍了基于注解的单表操作数据库的常用注解,包括@Insert、@Update、@Select、@Delete以及@Param注解等;然后讲解了基于注解的关联查询,包括一对一查询@One、一对多查询以及多对多查询@Many,在MyBatis框架中,这些注解十分的重要,熟练地掌握他们可以大大的提高开发的效率。


原文地址:https://blog.csdn.net/HLJ_Student/article/details/142805749

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!