Mybatis 注解(详细版)
前言
随着对mybatis 框架的学习和理解,我们发现真正需要频繁改动的是 mapper映射文件。
在mapper 映射文件中,我们时常 会根据具体的场景,写操作数据库的sql 语句以及操作数据库需要的环境【描述表与表之间的关联关系,参数类型,结果集类型等】。并且发现,每一个实体类都有一个对应的mapper 映射文件。
缺点:在实际开发中,发现,在编写mapper 映射文件,需要写大量的xml 配置。这是非常麻烦的!因此为了更加简单,简洁,才使用 注解的方式逐渐取代mapper 映射文件
基于注解的单表增删改查
使用注解描述增删改查操作,可以点击下面的博客链接,联合起来思考,方便理解
使用mybatis -基本的增删改查-CSDN博客
列举 @Select ,@insert ,@Update ,@Delete ,@Param 注解
任何demo(案例)准备工作
项目准备
1 tb_worker 数据表, 实体类 Worker 类
- tb_worker 数据表
- 实体类 Worker 类
2 使用log4j日志依赖 观察运行情况
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- 添加关于日志的配置文件:log4j.properties
# Set root logger level
log4j.rootLogger=DEBUG, stdout
# Set the log output format
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
- 在 mybatis-config 配置文件 启用日志
<settings>
<!-- 启用日志-->
<setting name="logImpl" value="LOG4J"/>
</settings>
- 注意:<settings> 标签应该放在 <properties>标签下
3 加载 WorkMapper接口 在mybatis-config 配置文件
<mapper class="fs.mapper.WorkMapper"></mapper>
列举 @Select ,@insert ,@Update ,@Delete ,@Param 注解
@Select 注解
提示:@Select 注解 用于映射查询语句,其作用等同于xml 配置文件 中的<select> 元素
demo(案例)
WorkMapper 接口
@Select("select * from tb_worker where id = #{id}") // 查询所有员工信息 public Worker selectWorker(int id);
运行截图
@insert 注解
提示:@insert 注解 用于映射插入语句,其作用等同于xml 配置文件 中的<insert> 元素
demo(案例)
WorkMapper 接口
// 插入员工信息 @Insert("insert into tb_worker(worker_id,name,sex,age) values(#{worker_id},#{name},#{sex},#{age})") public int insertWorker(Worker worker);
运行截图
@Update 注解
提示:@Update 注解 用于映射更新语句,其作用等同于xml 配置文件 中的<update> 元素
demo(案例)
WorkMapper 接口
// 更新 员工信息 @Update("update tb_worker set name = #{name},age = #{age} where id = #{id}") int updateWorker(Worker worker);
运行截图
@Delete 注解
提示:@Delete 注解 用于映射删除语句,其作用等同于xml 配置文件 中的<delete> 元素
demo(案例)
WorkMapper 接口
// 删除员工信息 @Delete("delete from tb_worker where id = #{id}") int deleteWorker( int id);
运行截图
@Param 注解
功能:@Param 注解是指定sql 语句中的参数,通常用于sql 语句中参数比较多的情况
demo(案例)
WorkMapper 接口
//通过员工 id 和员工姓名查询员工信息 @Select("select * from tb_worker where id = #{param01} and name = #{param02}") Worker selectWorkerByIdAndName(@Param("param01") int id,@Param("param02" ) String name);
具体步骤:给方法中的参数 起别名,并且别名一般是在参数的左边。如上图的代码, id 的别名是 param01 , name 的别名是 param02。同时还要id,name两个 参数的 别名,需要与@Select 注解的中的 “ #{ }” 中的名称 一一对应。这样 @Param 注解 用于将参数id,name 的值映射到#{param01} 和 #{param02) 中
运行截图
总结
1 在进行增删改操作时,最后记得提交事物,否则你修改的数据,不会保存到数据库中
sqlSession.commit();
2 理解 怎么调用WorkMapper 接口的方法
WorkMapper mapper = sqlSession.getMapper(WorkMapper.class);
查看底层代码,使用 动态代理技术,创建代理类 在某种程度上,实现了 WorkMapper 接口
下一步
进入MapperProxy 底层代码
基于注解的关联查询
可以点击下面这篇博客,相互学习 Mybatis 的关联映射(一对一,一对多,多对多)-CSDN博客
如何 学习注解的关联查询?
1 使用注解进行关联查询是 单表操作增删改查操作的延申,使用注解进行单表查询
2 学会关联查询中几个常用的注解
- @One:表示 表与表是一对一的关系 相当于在<resultMap>标签中的<association>元素
- @Many:表示 表与表是 一对多的关系,相当于<resultMap>标签中的<collection>元素
- @Results:在该注解中存在很多个@Result
@Result 注解相当于<resultMap>标签
- property 属性:用于指定关联的实体类属性
- column 属性:用于指定关联的数据库中表的字段
一对一查询
样图
Person 实体类
在WorkMapper 接口中,表之间是一对一关系,使用注解
注意:这两段代码,虽然表示的内容不同,但都是 一对一关系 表之间的查询,嵌套查询方式【多步到位】
在mapper 映射文件 表之间是 一对一关系,嵌套查询方式【多步到位】
<select id="findPersonById" parameterType="int" resultMap="card">
select * from tb_person where id = #{id}
</select>
<resultMap id="card" type="fs.pojo.Person">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<!-- 嵌套查询方式-->
<association property="card" column="card_id" javaType="fs.pojo.IdCard"
select="fs.mapper.IdCardMapper.findCodeById"/>
</resultMap>
分析
比较两端代码发现,@Result 等于 <resultMap>标签
1 为什么在mapper 映射文件中Person 实体类 的属性,映射的字段都写满了,而使用注解表示,却只映射两表的关联属性 card,其他的却没有?
答:使用 注解时,主体类 person 类的基属性可以自动完成映射,也被称为隐式映射。相较于显示映射而言,更加简洁
2 隐式映射 的应用场景?
答:MyBatis 有一个默认的映射规则,即如果字段名和数据库列名一致,MyBatis 会自动完成映射。例如,tb_person
表中的 id
列会自动映射到 Person
类的 id
属性,name
列会自动映射到 Person
类的 name
属性。
3 隐式映射 和显示映射的区别?
答:所有关系类型都可以使用隐式映射或显式映射,区别在于:
-
一对一关系:通常更简单,主表字段较少,隐式映射往往足够满足需求。
-
一对多或多对多关系:通常涉及集合字段(如
List<Order>
或List<Role>
),这些字段需要通过@Many
或@Collection
注解显式处理,但主表字段仍然可以使用隐式映射。
4 为什么说在列举的代码和图片中都使用了 嵌套查询方式实现映射文件?
嵌套查询方式在 mysql数据库中,可以理解为嵌套子查询
样例
SELECT p.id AS person_id, p.name,
(SELECT ic.id FROM tb_idcard ic WHERE ic.id = p.card_id) AS card_id,
(SELECT ic.number FROM tb_idcard ic WHERE ic.id = p.card_id) AS card_number
FROM tb_person p;
对比上面的代码,发现无论是否使用注解 ,都有一个select 属性,属性值为另一个被嵌套sql语句关联的接口的对应的方法的地址
地址一般格式表示为:接口路径+对应的方法名
一对多查询
样图
Orders 实体类
OrderMapper 接口
分析
@Result(id = true, property = "id", column = "id")
表示将数据库表中的id
列映射到Orders
类的id
属性,并且id
是主键(id = true
)。
@Result(property = "number", column = "number")
表示将数据库表中的number
列映射到Orders
类的number
属性。
@Result(property = "productList", column = "id", many = @Many(select = "fs.mapper.ProductMapper.selectProductByOrdersId"))
表示将订单中的产品列表(productList
)与订单 ID 关联,并通过ProductMapper.selectProductByOrdersId
方法进行查询。many
表示这是一个一对多的关系(一个订单可以包含多个产品)。
关于下面这行代码的解读
@Result(property = "productList",column = "id")
不使用注解在mapper 映射文件
注意:这两段代码,虽然表示的内容不同,但都是 一对多关系 表之间的查询,嵌套查询方式【多步到位】
样例
<select id="findOrdersWithProduct1" parameterType="int" resultMap="orders">
select * from tb_orders where id=#{id};
</select>
<resultMap id="orders" type="fs.pojo.Orders">
<id property="id" column="id"/>
<result property="number" column="number"/>
<collection property="productList" column="id" ofType="fs.pojo.Product" select="fs.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
多对多查询
需要构建一张中间表,维持两张表多对多这个关系。其他的和一对多,是一样的!