【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;
@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;
}
}
- 在项目的
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()
,具体代码如下:
@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();
}
- 运行结果应该是如下:
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()
,具体代码如下:
@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();
}
- 插入成功应该会在控制台返回如下内容:
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()
方法,具体代码如下:
@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();
}
- 输出结果应该是这样的:
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()
方法,具体代码如下:
@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();
}
- 输出结果应该是这样的:
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()
,具体代码如下:
@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();
}
- 正确输出结果应如下:
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()
,具体代码如下:
@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();
}
- 正确结果应该输出如下信息:
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()
方法,代码如下:
@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();
}
- 正确的查询结果应如下:
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()
方法,具体代码如下:
@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();
}
- 查询结果应如下所示:
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;
@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}
- 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}
- 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)!