SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第五天)MyBatis的注解开发

SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第五天)MyBatis的注解开发

​ 昨天我们深入学习了MyBatis多表之间的关联映射,了解掌握了一对一关联映射,一对多关联映射,嵌套查询方式以及嵌套结果方式,掌握了缓存机制的一级缓存,二级缓存等概念,也使用了代码进行复现理解。但是都是基于XML配置文件的方式来实现的,现在我们要学习一下Mybatis提供的更加简便的注解配置方式。


那么今天我们要掌握的是MyBatis的注解开发:

  • 掌握基于注解的单表增删改查
  • 掌握基于注解的关联查询

一、基于注解的单表增删改查

什么是注解?

Annotation(注解)就是Java提供了一种为程序元素关联任何信息或任何元数据(metadata)的途径和方法Annotion(注解)是一个接口程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据

注解不会影响程序代码的执行,Annotation能被用来为某个程序元素(类、方法、成员变量等)关联任何的信息。需要注意的是,这里存在着一个基本的规则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。


什么是MyBatis的注解开发?

MyBatis 支持通过注解来进行数据库操作,这种方式被称为 MyBatis 的注解开发。通过注解可以更直观地在 Java 代码中定义 SQL 语句,省去了繁琐的 XML 配置

MyBatis的注解开发通常需要使用接口来进行。

在我们项目的根目录java下,新建一个dao包。

DAO(Data Access Object)层是在软件架构中用于封装与数据库或其他持久化机制的交互的一种设计模式在典型的三层架构(或多层架构)中,DAO 层通常是位于持久化层的组成部分,它负责执行数据库操作,提供数据的增、删、改、查等基本操作,同时也可以包含一些复杂的查询逻辑它提供了一种抽象层,将应用程序的业务逻辑与底层的数据访问细节分离开来,使代码更加清晰、可维护和可测试。

②dao包中新建一个接口(interface):Bookmapper(如下图)

在这里插入图片描述

③BookMapper接口中编写上SQL放在方法的上方。
package dao;import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import pojo.Book;import java.util.List;public interface BookMapper {@Select("select * from book")List<Book> selectBook();@Select("select * from book where id =#{id}")Book getOneBookById(Integer id);@Update("update book set id=#{id},bookName=#{bookName},price=#{price},author=#{author}")Boolean updateALlItem(Book book);
}

我们之前有学过,SQl语句,那么就很简单能够理解了,抽出一小块理解一下

 @Select("select * from book")//相当于sql语句,用于访问数据库List<Book> selectBook();//相当于java里面的方法,返回值是List<Book>
  1. @Select("select * from book"): 这是一个用于查询的注解,表示执行了一个查询操作。括号中的内容是执行的SQL语句,这里查询语句的意思是查询整个 book 表的所有数据。
  2. List<Book>: 这是查询的返回类型,表示查询的结果将会被映射到一个 List 集合中,集合中的每个元素都是一个 Book 对象。
  3. selectBook(): 这是方法的名称,可以根据需要命名。当调用这个方法时,MyBatis会执行对应的SQL查询,并将结果映射到返回类型指定的集合中。记得使用了注解的话,就得对应写入方法,不然会报错。

这样的注解方式可以直接在接口中定义SQL查询语句,非常方便。MyBatis会在运行时根据这些注解执行对应的数据库操作。


④往mybatis-config.xml中注册注解。
    <mappers><mapper resource="mapper/PasswordMSMapper.xml"/><mapper resource="mapper/IdCardMapper.xml"/><mapper resource="mapper/PersonMapper.xml"/><mapper resource="mapper/UserMapper.xml"/><mapper resource="mapper/BookMapper.xml"/><mapper class="dao.BookMapper" /></mappers>

注意和以前的xml不同的是,这里是class,不是resource

<mapper class="dao.BookMapper" /> 是 MyBatis 配置文件中的一个元素,用于指定一个 DAO 接口对应的 Mapper 类。这个元素告诉 MyBatis 哪个接口的方法应该与 XML 映射文件中的 SQL 语句进行关联。

​ 在这里,<mapper class="dao.BookMapper" />作用是将名为 BookMapper 的 DAO 接口与 XML 映射文件关联起来,使得该接口的方法可以与 XML 文件中的 SQL 语句进行匹配,从而实现数据库的操作


⑤编写测试类查看效果
 @Testvoid findBookById() {//Annotation mode test注解方式查询数据库//1.创建SqlSession实例,用于连接数据库SqlSession session=MyBatisUtil.createSqlSession();//2.调用查询语句,传入参数查询List<Book> books=session.selectList("selectBook");//3.输出结果for(Book book:books){logger.info("ID:"+book.getId()+", 书名:"+book.getBookName()+",价格 :"+book.getPrice()+",作者:"+book.getAuthor());}session.close();//关闭连接,若是增删改这些业务操作需要先提交一下事务session.commit();}

在这里插入图片描述

可以发现能够正常的调用sql语句,并且访问数据库获取结果,但是呢红色圈标注的那里,一般我们要做修改成这样:表示调用BookMapper接口中的selectBook方法,这样更符合接口的调用习惯

 //2.调用查询语句,传入参数查询List<Book> books=session.getMapper(BookMapper.class).selectBook();

在这里插入图片描述

那么自行补充其他的注解语句,增删改查等,或者可以下载我的资源文件,里面全都写好了


二、掌握基于注解的关联查询

还是我们之前的场景一对一关联映射,一对多关联映射

①一对一关联映射Person和IdCard,先编写俩个类的Mapper接口文件,因为pojo类之前已经生成过了,前面几天中就用过了。

PersonMapper接口如下:

package dao;import org.apache.ibatis.annotations.*;
import pojo.IdCard;
import pojo.Person;@Mapper
public interface PersonMapper {// 根据id查询人员信息,并关联查询身份证信息@Select("SELECT * FROM person WHERE id = #{id}")@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "age", column = "age"),@Result(property = "sex", column = "sex"),@Result(property = "cardId", column = "id", javaType = IdCard.class, one = @One(select = "dao.IdCardMapper.getIdCardById"))})//这里就是经典的一对一关联映射了 javaType,One,Person getPersonWithIdCard(Integer id);// 插入人员信息@Insert("INSERT INTO person (name, age, sex, card_id) VALUES (#{name}, #{age}, #{sex}, #{cardId.id})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")void insertPerson(Person person);// 更新人员信息@Update("UPDATE person SET name = #{name}, age = #{age}, sex = #{sex}, card_id = #{cardId.id} WHERE id = #{id}")int updatePerson(Person person);// 删除人员信息@Delete("DELETE FROM person WHERE id = #{id}")int deletePerson(Integer id);
}

IdCardMapper接口如下:

package dao;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import pojo.IdCard;@Mapper
public interface IdCardMapper {@Select("SELECT * FROM idcard WHERE id = #{id}")IdCard getIdCardById(@Param("id") Integer id);//插入语句@Insert("INSERT INTO idcard (code) VALUES (#{code})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")void insertIdCard(IdCard idCard);
}
②mybatis-config.xml中写入注解注册
<mappers><mapper resource="mapper/PasswordMSMapper.xml"/><mapper resource="mapper/IdCardMapper.xml"/><mapper resource="mapper/PersonMapper.xml"/><mapper resource="mapper/UserMapper.xml"/><mapper resource="mapper/BookMapper.xml"/><mapper class="dao.BookMapper" /><mapper class="dao.PersonMapper" /><mapper class="dao.IdCardMapper" /></mappers>

记得是使用class元素不是resource了

③编写测试类查看一对一关联映射查询的情况

在这里插入图片描述

可以看到生成了俩个sql语句去进行数据库访问,这是因为我们使用了嵌套查询的方式

查看PersonMapper中的设定:

    @Result(property = "cardId", column = "id", javaType = IdCard.class, one = @One(select = "dao.IdCardMapper.getIdCardById"))
④稍微解释一下代码:

当使用 MyBatis 进行一对一关联查询时,我们需要告诉 MyBatis 如何将查询结果映射到 Java 对象中。这时我们会使用 @Result 注解来指定映射关系

  • property:表示 Java 对象中的属性,即要映射的属性名。
  • column:表示数据库中的列名,即查询结果中对应的列。
  • javaType:表示要映射到的 Java 类型,这里是 IdCard.class,表示要将查询结果映射为 IdCard 类型的对象。
  • one:表示一对一关系,这里使用了 @One 注解来指定关联查询的方法。

这段代码的作用是在执行一对一关联查询时,将查询结果中的 id 列映射到 Java 对象的 cardId 属性,并且通过 dao.IdCardMapper.getIdCardById 方法来查询与之关联的证件信息。这样,在查询 Person 信息的同时,也会查询并映射对应的 IdCard 信息。


接下来是一对多关联映射,一对多的场景就是我们之前的俩个表User和tb_Order

①一对一关联映射Users和TbOrder,先编写俩个类的Mapper接口文件,因为pojo类之前已经生成过了,前面几天中就用过了。

UserMapper接口如下:

package dao;import org.apache.ibatis.annotations.*;
import pojo.Users;
import pojo.TbOrder;import java.util.List;@Mapper
public interface UserMapper {@Select("SELECT * FROM users WHERE uid=#{id}")@Results({@Result(property = "uid", column = "uid"),@Result(property = "uname", column = "uname"),@Result(property = "uage", column = "uage"),@Result(property = "orderList", column = "uid", javaType = List.class, many = @Many(select = "dao.TbOrderMapper.findTheOrderByUserId"))})Users findTheOrderWithUserById(Integer id);
}

这里记得一对多是使用many,然后这里的javaType要改成List.class因为订单可能会有多条记录

TbOrderMapper接口如下:

package dao;import org.apache.ibatis.annotations.Select;
import pojo.TbOrder;import java.util.List;public interface TbOrderMapper {@Select("SELECT * FROM tb_order WHERE userid=#{id}")List<TbOrder> findTheOrderByUserId(Integer id);
}
②mybatis-config.xml中写入注解注册
 <mappers><mapper class="dao.BookMapper" /><mapper class="dao.PersonMapper" /><mapper class="dao.IdCardMapper" /><mapper class="dao.UserMapper" /><mapper class="dao.TbOrderMapper" /><mapper resource="mapper/PasswordMSMapper.xml"/><mapper resource="mapper/IdCardMapper.xml"/><mapper resource="mapper/PersonMapper.xml"/><mapper resource="mapper/UserMapper.xml"/><mapper resource="mapper/BookMapper.xml"/></mappers>

在这里插入图片描述

这一次要稍作修改,因为mybatis-config.xml文件中的扫描方式是从上往下扫描,所以<mappers>元素下引入UsersMapper和OrdersMapper接口的位置,必须在引入UserMapper.xml和TbOrderMapper.xml文件位置前面,否则程序将会首先读取到引入的UserMapper.xml和TbOrderMapper.xml文件,程序将有可能会报错。

③编写测试类:
//使用注解方式一对多关联查询订单信息通过id
@Test
void findTheOrderWithUserById(){SqlSession session = MyBatisUtil.createSqlSession();Users users=session.getMapper(dao.UserMapper.class).findTheOrderWithUserById(1);List<TbOrder> tbOrders=users.getOrderList();for (TbOrder order:tbOrders){logger.info("id"+users.getUid()+",姓名:"+users.getUname()+",年龄:"+users.getUage()+",产品名:"+order.getProductname()+",价格:"+order.getPrice()+",库存"+order.getNumber());}session.close();
}

输出结果如下:

在这里插入图片描述

成功显示一对多数据查询,那么要注意的是一对一一对多的数据插入等操作,记得先对单表进行操作,再去更新有外键的表,这样才不会报错,出现误读。


以下是一些常用的 MyBatis 注解及其用法:

  1. @Select:用于查询操作。

    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(int id);
    
  2. @Insert:用于插入操作。

    @Insert("INSERT INTO users (id, username, email) VALUES (#{id}, #{username}, #{email})")
    int insertUser(User user);
    
  3. @Update:用于更新操作。

    @Update("UPDATE users SET username = #{username}, email = #{email} WHERE id = #{id}")
    int updateUser(User user);
    
  4. @Delete:用于删除操作。

    @Delete("DELETE FROM users WHERE id = #{id}")
    int deleteUser(int id);
    
  5. @Result@Results:用于定义结果映射。

    @Results({@Result(column = "id", property = "id"),@Result(column = "username", property = "username"),@Result(column = "email", property = "email")
    })
    @Select("SELECT * FROM users")
    List<User> getAllUsers();
    
  6. @Param:用于传递参数。

    @Select("SELECT * FROM users WHERE username = #{username} AND email = #{email}")
    User getUserByUsernameAndEmail(@Param("username") String username, @Param("email") String email);
    
  7. @Options:用于设置一些选项,如主键返回,主键自增等

    @Insert("INSERT INTO users (username, email) VALUES (#{username}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertUser(User user);
    
  8. @ResultMap:引用在 XML 配置文件中定义的 ResultMap。

    @ResultMap("UserResultMap")
    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(int id);
    

使用注解开发可以更紧凑地定义数据库操作,但对于复杂的动态 SQL 或多表关联查询,通常 XML 配置更为灵活和可读。在实际项目中,你可以根据场景选择使用注解还是 XML 配置,甚至两者结合使用。


总结

今天是Mybatis学习的第五天,今天学的Mybatis的注解开发。其实需要详细理解一下,然后自己去完成一下注解方式单表的增删改,还有注解方式的多表关联查询,嵌套条件方式和嵌套结果方式。看似简单,实则需要自己动手操作才能彻底掌握,理解清楚多表之间的关系,哪个表必须先处理,然后怎么样去嵌套获取信息等。还有今天了解一些注解关键字,虽然看着熟悉,实际上使用的话,还是会有一些坑要踩的,需要慢慢理解。

​ 想要跟着学习的可以去我的资源里面找对应的文件下载,我的md文件也会发上去,项目文件会上传可以自己跟着学习一下。

PS:还可以自己学着掌握使用Mybatis和Xml联合开发的方式,或者我后面单独放一章出来讲

作者:Stevedash

发表于:2023年8月27日 14点40分

注:本文内容基于个人学习理解,如有错误或疏漏,欢迎指正。感谢阅读!如果觉得有帮助,请点赞和分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序如何实现页面传参和页面传递多个参数

前言 只要你的小程序超过一个页面那么可能会需要涉及到页面参数的传递&#xff0c;下面我总结了 4 种页面方法。 下面时多个参数页面传参的方式 let loveJSON.stringify(this.data.totle);let youJSON.stringify(this.data.totleId)let csdnJSON.stringify(this.data.totleP…

Linux系统下vim常用命令

一、基础命令&#xff1a; v:可视模式 i:插入模式 esc:命令模式下 :q &#xff1a;退出 :wq &#xff1a;保存并退出 ZZ&#xff1a;保存并退出 :q! &#xff1a;不保存并强制退出二、在Esc下&#xff1a; dd : 删除当前行 yy:复制当前行 p:复制已粘贴的文本 u:撤销上一步 U:…

ELK日志收集系统

目录 一、概述 二、组件 一、logstash 一、工作过程 二、INPUT 三、FILETER 四、OUTPUTS 二、elasticsearch 三、kibana 三、架构类型 一、ELK 二、ELKK 三、ELFK 四、ELFKK 五、EFK 四、配置ELK日志收集系统集群实验的步骤文档 五、配置ELK日志收集系统集群 …

图像二值化

目录 1.固定值二值化 2.自适应阈值二值化 3.Android JNI完整代码 1.固定值二值化 固定阈值二值化是OpenCV中一种简单而常用的图像处理技术&#xff0c;用于将图像转换为二值图像。在固定阈值二值化中&#xff0c;像素值根据一个预定义的阈值进行分类&#xff0c;大于阈值的…

【JavaEE】Spring事务-@Transactional参数介绍-事务的隔离级别以及传播机制

【JavaEE】Spring 事务&#xff08;2&#xff09; 文章目录 【JavaEE】Spring 事务&#xff08;2&#xff09;1. Transactional 参数介绍1.1 value 和 transactionManager1.2 timeout1.3 readOnly1.4 后面四个1.5 isolation 与 propagation 2. Spring 事务隔离级别 - isolation…

利用torchvision库实现目标检测与语义分割

一、介绍 利用torchvision库实现目标检测与语义分割。 二、代码 1、目标检测 from PIL import Image import matplotlib.pyplot as plt import torchvision.transforms as T import torchvision import numpy as np import cv2 import randomCOCO_INSTANCE_CATEGORY_NAMES …

SQL server数据库-定制查询-指定查询列/行、结果排序和Like模糊查询

本篇讲述进阶查询方法&#xff0c;如有语句不明确&#xff0c;可跳转本文专栏学习基础语法 1、指定列查询 特点 只会显示你输入的列的数据&#xff0c;会根据你输入的顺序进行显示&#xff0c;可以自定义查询显示时的列名 &#xff08;1&#xff09;只会显示你输入的列的数…

C++ 面试题(一)--C++基础,面向对象,内存管理

目录 1.part1 C基础 1 C特点 2 说说C语言和C的区别 3 说说 C中 struct 和 class 的区别 4 include头文件的顺序以及双引号""和尖括号<>的区别 5 说说C结构体和C结构体的区别 6 导入C函数的关键字是什么&#xff0c;C编译时和C有什么不同&#xff1f; 7…

系统架构设计高级技能 · 云原生架构设计理论与实践

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…

新能源汽车动力总成系统及技术

需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer …

使用Python构建网络爬虫:提取网页内容和图片资源

网络爬虫是一种自动获取网页内容的程序&#xff0c;它可以帮助我们高效地收集网络上的有价值信息。本文将介绍如何使用Python构建网络爬虫&#xff0c;提取网页内容和图片资源。   一、环境准备   1.安装Python环境   首先&#xff0c;确保您已经安装了Python环境。访问P…

kettle实现爬虫

步骤概览 获取请求 请求地址 东方财富网股票请求 自定义常量数据 获取HTTP请求之前&#xff0c;必须先定义一个URL常量作为HTTP client的输入 HTTP client 注&#xff1a;此处得到的数据并不是原生的json字符串&#xff0c;自己可以用文本文件输出测试以下。如下图 JavaScri…

QT登陆注册界面练习

一、界面展示 二、主要功能界面代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QMainWindow(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setFixedSize(540,410); //设置固定尺寸th…

android Junit4编写自测用例

10多年的android开发经验&#xff0c;一直以来呢&#xff0c;也没有使用过android自带的测试代码编写。说来也惭愧。今天也花了点时间稍微研究了下。还挺简单。接下来就简单的说一下。 新建工程 直接默认新建一个工程&#xff0c;就会有两个目录androidTest和test(unitTest)两…

CSS中如何改变鼠标指针样式(cursor)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS中改变鼠标指针样式&#xff08;cursor&#xff09;⭐ 示例&#xff1a;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅…

免费OCR图像识别文字识别API

免费OCR图像识别文字识别API 一、OCR图像识别文字识别二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、温馨提示 一、OCR图像识别文字识别 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;是指对文本资料的图像文件进行分析识别…

Visual Studio 2022的MFC框架——AfxWinMain全局对象和InitInstance函数

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 在看这篇帖子前&#xff0c;请先看我的另一篇帖子《Visual Studio 2022的MFC框架——应用程序向导》。 当程序调用了CWinApp类的构造…

No message found under code ‘-1‘ for locale ‘zh_CN‘.

导出中的报错&#xff1a;No message found under code -1 for locale zh_CN. 报错原因&#xff1a;页面中展示的数据和后端excel中的数据不一致导致 具体原因&#xff1a;

【记录】Truenas scale|NFSv4数据集的子目录或文件的ACL完全访问权限继承老是继承不了怎么回事

我遇到了数据集下新建文件夹或文件&#xff0c;新建的文件夹或文件没有和数据集的ACL设置相符合的情况。其根本原因是NFSv4的完全访问权限要想继承的话&#xff0c;它的访问设置权限要设置“用户”和“组”的&#xff0c;就是&#xff0c;一定要选择中文的那个设置。纯owner和g…

FairyGUI编辑器的弹窗操作【插件】

之前在FairyGUI编辑器菜单扩展中&#xff0c;我使用了App.Alert("复制失败")来提示操作是否成功。这篇则会说一下我们可以使用的弹窗提示&#xff0c;以及做到类似资源发布成功时的“发布成功”飘窗。 打开APP的API脚本&#xff0c;可以看到有很多公开方法&#xff…