【Java_EE】Day05 MyBatis注解开发
Day05 MyBatis注解开发
基于注解的单表增删改查
除了前四节我们使用XML的映射方式进行开发,其实我们更常用的方式是通过Mybatis的注解实现POJO实体对象和数据表,一般我们直接把他写在接口上。这样的好处在于相对来讲更简单,而且不会增加开销。MyBatis提供了@Select
、@Insert
、@Update
、@Delete
以及@Param
等用于增删改查,以及传递参数的常用注解。
@Select注解
@Select
注解用于映射查询语句,下面通过根据员工id
查找员工信息的案例来演示一下如何使用注解进行开发。
- 在
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);
- 在项目
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;@Overridepublic 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;}
}
- 在项目的
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);
}
- 在核心配置文件
mybatis-config.xml
中的<mappers>
元素下引入WorkerMapper
接口,将WorkerMapper.java
接口加载到核心配置文件中,具体代码添加如下:
<mapper class="com.itheima.dao.WorkerMapper"/>
- 为了验证上述配置,在测试类
MybatisTest
中编写测试方法findWorkerByIdTest()
,具体代码如下:
@Testpublic 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();}
- 运行结果应该是如下:
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
注解用于映射插入语句,下面通过实现员工信息的插入案例来演示,具体步骤如下:
- 在
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);
- 为了验证上述配置,我们在测试类中编写测试方法
insertWorkerTest()
,具体代码如下:
@Testpublic 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();}
- 插入成功应该会在控制台返回如下内容:
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
注解用于映射更新语句,下面通过实现员工信息的修改案例来说一说这个注解该如何使用。
- 在
WorkerMapper
接口中添加更新tb_worker
表中数据的方法,并在方法上添加@Update
注解,具体代码如下:
@Update("UPDATE mybatis.tb_worker SET name=#{name} WHERE id=#{id}")int updateWorker(Worker worker);
- 为了验证上述配置,在测试类
MyBatisTest
中添加测试方法updateWorkerTest()
方法,具体代码如下:
@Testpublic 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();// 关闭sessionsession.close();}
- 输出结果应该是这样的:
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
注解用于映射删除语句,实现数据库信息的删除,为具体演示,我们通过实现员工信息删除的案例如下:
- 在
WorkerMapper
接口中添加删除数据库中数据的方法,并在方法上添加@Delete
注解标注的deleteWorker()
方法时,@Delete
注解中映射的删除语句将会被执行:
@Delete("DELETE FROM mybatis.tb_worker WHERE id=#{id}")int deleteWorker(int id);
- 为了验证上述配置,我们在测试类中编写方法
deleteWorkerTest()
方法,具体代码如下:
@Testpublic 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();//关闭sessionsession.close();}
- 输出结果应该是这样的:
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
和姓名查询员工信息的案例来具体演示一下:
- 在
WorkerMapper
接口中添加多条件查询的方法,具体代码如下:
@Select("SELECT * FROM mybatis.tb_worker WHERE id=#{param01} AND name=#{param02}")Worker selectWorkerByWorkerId(@Param("param01") int id, @Param("param02") String name);
- 编写测试方法
selectWorkerByWorkerIdTest()
,具体代码如下:
@Testpublic 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();}
- 正确输出结果应如下:
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_idcard
和tb_person
数据表为例,感受基于@One
注解实现tb_person
数据表之间的一对一关联查询。
- 在项目的
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);
}
- 在项目的
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);
}
- 在核心配置文件中引入这两个
Mapper
接口,具体引入代码如下:
<mapper class="com.itheima.dao.PersonMapper"/>
<mapper class="com.itheima.dao.IdCardMapper"/>
- 为了验证上述配置,我们在测试类中编写测试方法
selectPersonByIdTest()
,具体代码如下:
@Testpublic 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();}
- 正确结果应该输出如下信息:
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_user
和tb_orders
数据表为例,讲解基于@Many
注解配置实现tb_user
和tb_orders
数据表之间的一对多关联查询。
- 在项目的
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);
}
- 在项目的
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);
}
- 将这两个Mapper引入到核心加载配置文件中,代码如下:
<mapper class="com.itheima.dao.OrdersMapper"/><mapper class="com.itheima.dao.UsersMapper"/>
- 为了验证上述配置,我们在测试类中添加
selectUserByIdTest()
方法,代码如下:
@Testpublic 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();}
- 正确的查询结果应如下:
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_orders
和tb_product
数据表之间基于注解的多对多关联查询,具体步骤如下:
- 在项目的
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);
}
- 在项目的
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);
- 在核心配置文件中引入
ProductMapper
接口,由于OrdersMapper
已经引入过了,所以无需再次引入,具体代码如下:
<mapper class="com.itheima.dao.ProductMapper"/>
- 为了验证上述配置,我们在测试类中编写
selectOrdersByIdTest()
方法,具体代码如下:
@Testpublic 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();}
- 查询结果应如下所示:
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 | 张三 | 18 | 1 |
2 | 李四 | 18 | 2 |
3 | 王五 | 19 | 2 |
4 | 赵六 | 20 | 1 |
班级id(id) | 班级名称(classname) |
---|---|
1 | 一班 |
2 | 二班 |
需求如下,请使用MyBatis注解完成以下要求:
-
MyBatis注解实现查询操作。根据上表在数据库分别创建一个学生表
s_student
和一个班级表c_class
,并查询id
为2的学生信息。 -
MyBatis注解实现修改操作。将
id
为4的学生姓名修改为李雷,年龄修改为21。 -
MyBatis注解实现一对多查询。查询出二班所有学生的信息。
代码实现:
需求如下,请使用MyBatis注解完成以下要求:
- 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
包下创建持久化类SStudent
和CClass
,并添加数据库所有属性以及getter/setter
、toString()
方法。
SStudent.java
package com.itheima.pojo;/*** @author Zhang*/
public class SStudent {private Integer id;private String name;private Integer age;private Integer cid;@Overridepublic 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;@Overridepublic 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()
方法,如下代码:
@Testpublic 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}
- MyBatis注解实现修改操作。将
id
为4的学生姓名修改为李雷,年龄修改为21。
在SStudentMapper
接口中定义一个updateStudentById()
方法,代码如下:
@Update("UPDATE mybatis.s_student " +"SET name = #{name}, age = #{age} " +"WHERE id = #{id}")int updateStudentById(SStudent student);
为了验证上述配置是否生效,我们在测试类中编写updateStudentByIdTest()
测试方法,代码如下:
@Testpublic 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}
- 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;@Overridepublic 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()
方法,代码如下:
@Testpublic 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框架中,这些注解十分的重要,熟练地掌握他们可以大大的提高开发的效率。