文章目录
- 一、单表查询
- 1. @Select 注解
- 2. @Insert 注解
- 3. @Update 注解
- 4. @Delete 注解
- 5. @Param 注解
- 二、多表关联查询
- 1. 一对一查询
- 2. 一对多查询
- 3. 多对多查询
一、单表查询
1. @Select 注解
前面的章节介绍了 MyBatis 的基本用法、关联映射、动态 SQL 和缓存机制等知识,所有的配置都是基于 XML 文件完成的,但在实际开发中,大量的 XML 配置文件的编写是非常繁琐的,为此,MyBatis 提供了更加简便的基于注解的配置方式。本篇将对 MyBatis 的注解开发进行详细讲解。
① 在项目的 com.tyut.pojo 包下创建持久化类 Worker,在 Worker 类中定义 id、员工姓名、年龄、性别、工号等属性以及属性对应的 getter/setter 方法。
② 在 com.tyut.dao 包下创建 WorkerMapper 接口,用于编写 @Select 注解映射的 select 查询方法。
package com.tyut.dao;
import com.tyut.pojo.Worker;
import org.apache.ibatis.annotations.Select;
public interface WorkerMapper {
@Select("select * from tb_worker where id = #{id}")
public Worker selectWorker(int id);
}
与之前不同的是,之前我们的 SQL 语句是写在 XML 映射文件中的,现在我们是注解开发不再需要 XML 了,而是去创建一个接口类,编写注解映射的 SQL 方法。
注意接口类的名字是有规范的,表名加 Mapper 的格式!
③ 因为不再是映射文件了,而是一个接口,所以需要在核心配置文件中引入 WorkerMapper 接口,告诉 MyBatis 我们的接口在哪里。
<mapper class="com.tyut.dao.WorkerMapper"/>
注意这里是 class 属性,不是 resource!
④ 编写测试方法,我们通过 MyBatis 的固定 API session.getMapper(WorkerMapper.class) 得到接口对象,然后就可以调用接口的方法了。
public void findWorkerByIdTest() {
//1.获取SqlSession对象
SqlSession session = MyBatisUtils.getSession();
WorkerMapper mapper = session.getMapper(WorkerMapper.class);
//2.查询id为1的员工信息
Worker worker = mapper.selectWorker(1);
System.out.println(worker);
//3.关闭SqlSession
session.close();
}
为了减少代码量,其实我们可以把公共部分写在 Before 和 After 中,代表每做一次 Test 都会先去执行 Before,并且最后执行一遍 After,而在 Test 中直接调用接口方法即可。
2. @Insert 注解
① 在 WorkerMapper 接口中添加插入数据的方法 insertWorker(),并在方法中添加 @Insert 注解。
@Insert("insert into tb_worker(name, age, sex, worker_id)"+"values(#{name}, #{age}, #{sex}, #{worker_id})")
public int insertWorker(Worker worker);
② 编写测试类
public void insertWorkerTest() {
//1.生成SqlSession对象
SqlSelssion 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);
//2.插入员工信息
int result = mapper.insertWorker(worker);
System.out.println(result);
//3.手动提交修改并关闭SqlSession
session.commit();
session.close();
}
3. @Update 注解
① 在 WorkerMapper 接口中添加更新数据的方法,并在方法中添加 @Update 注解。
@Update("update tb_worker set name = #{name}, age = #{age}"+"where id = #{id}")
public int updateWorker(Worker worker);
② 编写测试类
public void updateWorkerTest() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
Worker worker = new Worker();
worker.setId(4);
worker.setName("李华");
worker.setAge(28);
WorkerMapper mapper = session.getMapper(WorkerMapper.class);
//2.更新员工信息
int result = mapper.updateWorker(worker);
System.out.println(result);
//3.手动提交修改并关闭SqlSession
session.commit();
session.close();
}
4. @Delete 注解
① 同样,在 WorkerMapper 接口中添加删除数据的方法,并在方法上添加 @Delete 注解。
@Delete("delete from tb_worker where id = #{id}")
public int deleteWorker(int id);
② 编写测试类
public void deleteWorkerTest() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
WorkerMapper mapper = session.getMapper(WorkerMapper.class);
//2.删除员工信息
int result = mapper.deleteWorker(4);
if(result > 0) {
System.out.println("成功删除"+result+"条数据");
} else {
System.out.println("删除数据失败");
}
//3.手动提交修改并关闭SqlSession
session.commit();
session.close();
}
增删改操作需要手动去提交!
5. @Param 注解
下面通过一个案例来演示 @Param 注解的使用,该案例要求根据员工的 id 和姓名查询员工信息,具体步骤如下:
① 添加注解,在 WorkerMapper 接口中添加多条件查询的方法。
@Select("select * from tb_worker where id = #{param01} and name = #{param02}")
public Worker selectWorkerByIdAndName(@Param("param01") int id, @Param("param02") String name);
param01 和 param02 是我们给这两个参数分别起的别名!
② 编写测试类
public void selectWorkerByIdAndNameTest() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
WorkerMapper mapper = session.getMapper(WorkerMapper.class);
//2.查询id为3姓名为王五的员工的信息
Worker worker = mapper.selectWorkerByIdAndName(3,"王五");
System.out.println(worker);
session.close();
}
二、多表关联查询
1. 一对一查询
根据 person 的 id 查询人的信息,以及 IdCard 的信息。
Mybatis 注解式开发多表查询的前提是,将一条多表查询的 SQL,拆分成多条单表查询的 SQL!
① 创建 Person 和 IdCard 的两个实体类
//Person.java
package com.tyut.pojo;
public class Person {
private int id;
private String name;
private int age;
private String sex;
//一对一的映射
private IdCard card;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", card=" + card +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public IdCard getCard() {
return card;
}
public void setName(IdCard card) {
this.card = card;
}
}
//IdCard.java
package com.tyut.pojo;
public class IdCard {
private int id;
private String code;
@Override
public String toString() {
return "IdCard{" +
"id=" + id +
", code='" + code + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
② 在 com.tyut.dao 包下创建 IdCardMapper 接口 和 PersonMapper 接口,关键在于第二个接口的编写
//IdCardMapper.java
package com.tyut.dao;
import com.tyut.pojo.IdCard;
import org.apache.ibatis.annotations.Select;
public interface IdCardMapper {
@Select("select * from tb_idcard where id = #{id}")
public IdCard selectIdCardById(int id);
}
//PersonMapper.java
package com.tyut.dao;
import com.tyut.pojo.Person;
import org.apache.ibatis.annotations.Select;
public interface PersonMapper {
@Select("select * from tb_person where id = #{id}")
@Results(@Result(column = "card_id", property = "card",
one = @One(select = "com.tyut.dao.IdCardMapper.selectIdCardById")
))
public Person selectPersonById(int id);
}
@Result 注解的三个属性及含义:
(1)property 属性用来指定关联属性,这里为 card;
(2)column 属性用来指定关联的数据库表中的字段,这里为 card_id;
(3)one 属性用来指定数据表之间属于哪种关联关系,通过 @One 注解表明数据表 tb_idcard 和 tb_person 之间是一对一关联关系。
③ 在核心配置文件中引入接口
<mapper class="com.tyut.dao.IdCardMapper"/>
<mapper class="com.tyut.dao.PersonMapper"/>
要注意接口的引入顺序,由于 MybatisConfig.xml 文件的扫描方式是从上往下扫描,所以先引入 IdCardmapper,后引入 PersonMapper!
④ 编写测试类
public void selectPersonByIdTest() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
PersonMapper mapper = session.getMapper(PersonMapper.class);
//2.查询id为1的人员信息
Person person = mapper.selectPersonById(1);
System.out.println(person);
session.close();
}
2. 一对多查询
基于用户与订单的关系演示一对多查询,这里实体类我仅展示部分代码,完整代码可参考我前面的文章 —— MyBatis 关联映射,实体类完全一致,不再重复。
① 在 com.tyut.dao 包下创建 OrdersMapper 接口 和 UsersMapper 接口
//OrdersMapper.java
public interface OrdersMapper {
@Select("select * from tb_orders where user_id = #{id}")
@Results(@Result(id = true, column = "id", property = "id"),
@Result(column = "number", property = "number")
)
public List<Orders> selectOrdersByUserId(int user_id);
}
id = true 代表此处是主键映射,当实体的属性名与数据表的列名一致时,映射这一步骤可以省略!
//UsersMapper.java
public interface UsersMapper {
@Select("select * from 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.tyut.dao.OrdersMapper.selectOrdersByUserId"))
)
public Users selectUserById(int id);
}
② 编写测试类
public void selectUserById() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
UsersMapper mapper = session.getMapper(UsersMapper.class);
//2.查询id为1的用户订单信息
Users users = mapper.selectUserById(1);
System.out.println(users);
session.close();
}
3. 多对多查询
多对多关联关系通常使用一个中间表来维护,我们依然以前面的订单表和商品表为例进行演示,根据订单的 id 查询订单信息以及订单对应的商品信息。
① 在 com.tyut.dao 包下创建 ProductMapper 接口 和 OrdersMapper 接口
//ProductMapper.java
public interface ProductMapper {
@Select("select * from tb_product where id in (select product_id from tb_ordersitem where orders_id = #{id})")
public List<Product> selectProductByOrdersId(int orders_id);
}
//OrdersMapper.java
public interface OrdersMapper {
@Select("select * from 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.tyut.dao.ProductMapper.selectProductByOrdersId"))
)
public Orders selectOrdersById(int id);
}
② 编写测试类
public void selectOrderById() {
//1.生成SqlSession对象
SqlSession session = MyBatisUtils.getSession();
OrdersMapper mapper = session.getMapper(OrdersMapper.class);
//2.查询id为1的订单信息及订单对应的商品信息
Orders orders = mapper.selectOrderById(1);
System.out.println(orders);
session.close();
}