[Spring MVC3]MyBatis详解

news2024/11/20 23:19:01

本章重点讲述了MyBatis映射器,对数据层进行的操作,建议本篇文章和Spring Boot的持久层相互比较来看会更加收获颇多Spring Boot持久层技术

本文需要使用到MVC第一讲的模板格式与配置情况,全部代码已经放在此博客中,Spring MVC1

目录

  • MyBatis映射器
    • 映射器主要元素
    • select 元素
    • insert 元素
    • update元素
    • delete元素
    • sql元素
  • 动态SQL
    • if元素
  • Mybatis注解配置
    • 常用注解
  • MyBatis关联映射
  • 思考:DAO与Service层

MyBatis映射器

映射器主要元素

元素描述
select映射查询
insert映射插入
update映射更新
delete映射删除
sql可以被其他语句引用的可重用语句块
resultMap描述层数据库结果集加载对象
cache缓存配置
cache-ref缓存配置的引用

注意MyBatis的配置我是在AyUserMapper.xml进行配置,所定位的Dao层如下图查看,通过mapper标签对dao接口进行一对一的映射,这是相对复杂的xml配置,后面会讲到注解的方式
在这里插入图片描述
同时在applicationContext.xml进行扫描:
在这里插入图片描述

select 元素

可以从数据库读取数据,组装数据给业务人员。比如在AyUserMapper.xml使用select元素,根据id查找(相关文件与建表命令在Spring MVC1列出)
AyUserMapper.xml

<select id="findById" parameterType="String" resultType="com.ay.model.AyUser">
        select * from ay_user where id = #{id}
    </select>

这个语句就是findById,接收一个String类型的参数,并返回一个User.#{id}就是预处理语句,类似于:

String findById = "select * from ay_user where id = ?";
PreparedStatement ps = conn.prepareStatement(findById);
ps.setString(1,id);

在接口AyUserDao,AyUserService写下此方法:

AyUser findById(String id);

在AyUserServiceImpl:

public AyUser findById(String id) {
        return ayUserDao.findById(id);
    }

下面进入到控制层进行测试:AyUserController:

@GetMapping("/findById")
    public String findById(Model model) {
        AyUser m = null;
        m=ayUserService.findById("1");
        System.out.println(m.getName()+"AAA");
        return "hello";
    }

运行,浏览器输入80/user/findById,可以在控制台看到相应的信息
在这里插入图片描述
xml中的select id注意要和DAO接口的方法名要一致,否则不一致会抛出异常。
resultType:从语句返回期望类型的类完全限定类名;

下面再来看几个例子:

<select id="countByName" parameterType="String" resultType="int">
        select count(*) from ay_user
    </select>

对于的AyUserDao如下:

int countByName(String name);

insert 元素

用来映射DML语句,MyBatis会在执行插入后返回一个整数,来表示操作后的记录数。
下面的属性如下:

属性描述
useGeneratedKeys令MyBatis使用JDBC来获取数据库的主键
keyColumn指明第几列为主键,不与keyProperty公用
keyProperty指明哪个列作为主键
下面来看几个例子:
<insert id="insertUserTest" parameterType="com.ay.model.AyUser">
        insert into ay_user(id,name,password) values(#{id},#{name},#{password});
    </insert>
//或者使用主键自增的方法
<insert id="insertUserTest1" useGeneratedKeys="true" keyProperty="id" parameterType="com.ay.model.AyUser">
        insert into ay_user(name,password) values(#{name},#{password});
    </insert>

对应的AyUserDao,AyUserService接口如下:

int insertUserTest(AyUser ayUser);

实现的AyUserServiceImpl:

public int insertUserTest(AyUser ayUser){
       return ayUserDao.insertUserTest(ayUser);
    }

在控制层进行测试:

 @GetMapping("/insertUserTest")
    public String insertUserTest(Model model) {
        AyUser m =new AyUser();
        m.setId(9);m.setName("ccc");m.setPassword("1234");
        int t=ayUserService.insertUserTest(m);
        System.out.println(t);
        return "hello";
    }

运行80/user/insertUserTest,此时查看数据库信息:
在这里插入图片描述

update元素

用来映射DML语句,主要用来更新数据,同样也会返回一个整数来表示更新的记录数,和select属性差不多。

<update id="updateUser" parameterType="com.ay.model.AyUser">
        update ay_user set name = #{name},password = #{password} where id = #{id}
    </update>

在AyUserDao,AyUserService接口实现:

 int updateUser(AyUser ayUser);

在AyUserServiceImpl中实现:

public int updateUser(AyUser ayUser) {
        return ayUserDao.updateUser(ayUser);
    }

在控制层实现:

@GetMapping("/updateUser")
    public String updateUser(Model model) {
        AyUser m = new AyUser();
        m.setId(1);m.setName("jacinx");m.setPassword("88888");
        int t = ayUserService.updateUser(m);
        return "hello";
    }

运行80/user/updateUser,查看数据库信息:
在这里插入图片描述

delete元素

用来映射删除,和select差不多,这里就稍微写一下xml:

//根据Id删除记录
<delete id ="delete" parameterType = "int">
delete from ay_user where id = #{id}
</delete>

sql元素

sql元素可以用来定义可重用的SQL代码,可以被静态参数化,可以对字段进行封装:

<sql id="userField">
        a.id as "id",
        a.name as "name",
        a.password as "password"
    </sql>
<!--    获取所有用户-->
    <select id="findAll" resultType="com.ay.model.AyUser">
        select
        <include refid="userField"/>
            from ay_user as a

    </select>

当然方便地使用include元素的refid属性进行引用,还可以使用定制使用sql元素,具体如下:

<sql id="userField">
//注意使用$而不是使用#
        ${prefix}.id as "id",
        ${prefix}.name as "name",
        ${prefix}.password as "password"
    </sql>

#与$区别:
#{}将传入的数据当成字符串,会自动加一个双引号,例如:

order by #{id}
//如果id传入为11,那么解析成
order by "11"

${}将数据直接显示在sql中

order by ${id}
order by 11

#方式可以防止sql注入,$无法防止!

动态SQL

在项目开发中,经常根据不同的条件拼接SQL语句,而MyBatis提供了对SQL语句动态的组装能力。采用功能强大的基于OGNL表达式来完成动态SQL。

属性描述
if单条件分支
choose、when、otherwise多条件判断语句,相当于case when
trim、where、set用来处理SQL拼接问题,辅助元素
foreach循环语句

if元素

用来判断语句,比如按照name查询,name可填可不填,如果没填那么就不要使用它来作为查询条件。
if标签常常与test属性联合使用且是必选属性。下面的代码来判断name 或者password是否为空,如果不为空那么就拼凑sql进行查询,如果为空则忽略:

<resultMap id="userMap" type="com.ay.model.AyUser">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="password" column="password"/>
    </resultMap>
    <select id="findByNameAndPassword" parameterType="String" resultMap="userMap">
        select <include refid="userField"></include>
            from ay_user a where 1 = 1
            <if test="name != null and name !=''">
                and name = #{name}
            </if>
            <if test="password !=null and password !=''">
                and password = #{password}
            </if>
    </select>

在AyUserDao,AyUserService接口方法:

    List<AyUser> findByNameAndPassword(@Param("name") String name,@Param("password") String password);

在AyUserServiceImpl实现接口的方法:

public List<AyUser> findByNameAndPassword(@Param("name") String name, @Param("password") String password) {
        return ayUserDao.findByNameAndPassword(name,password);
    }

在控制层实现:

  @GetMapping("/findByNameAndPass")
    public String findByNameAndPass(Model model) {
        List<AyUser> a = null;
        a = ayUserService.findByNameAndPassword("ccc","1234");
        for(int i=0;i<a.size();i++) {
            System.out.println(a.get(i).getId()+"  "+a.get(i).getName());
        }
        return "hello";
    }

运行80/user/findByNameAndPass,可以看到控制台打印出相应的信息:

在这里插入图片描述
关于其他的元素例如foreach等就不再赘述了。

Mybatis注解配置

常用注解

除了前面的xml的配置方法,可以使用基于注解的配置方式!
在这里插入图片描述

@Select注解与xml的select相对应,@Results注解与resultMap标签相对应,当使用注解的时候就不用在xml配置了:
在AyUserDao层接口方法:

@Select("select * from ay_user ")
    List<AyUser> findAllUser();

其他AyUserService不变

List<AyUser> findAllUser();

在AyUserServiceImpl中:

public List<AyUser> findAllUser() {
        return ayUserDao.findAllUser();
    }

在控制层实现测试:

@GetMapping("/findAlUser")
    public String findAlUser(Model model) {
        List<AyUser> a = null;
        a = ayUserService.findAllUser();
        for(int i=0;i<a.size();i++) {
            System.out.println(a.get(i).getName());
            System.out.println();
        }
        return "hello";
    }

此时运行就能看到输出了。

其他的例如@Insert,@Update,@Delete类似

@Insert("insert into ay_user(name,password) values(#{name},#{password})")

当映射器需要多个参数,@Param注解可以被应用于映射器方法参数给每个参数取名字。

    List<AyUser> findByNameAndPassword(@Param("name") String name,@Param("password") String password);

MyBatis关联映射

在实际的项目中,需要遵循数据库设计范式的要求,对现实中的业务模块进行拆分,封装到不同的数据表中,表和表之间存在一对多或者多对多的对应关系。进而,对数据库的增删改查的主体从单表就变成了多表。

这里就不再赘述了。

思考:DAO与Service层

不知大家发现没有,在我的上述代码中,DAO与Service层的代码都是一样的,当然这是由于我是表单模式下的。所以这就引发我对DAO与Service层的思考:
这里引用一下zhihu的问题:java为什么要分为service层,dao层,controller层?
在这里插入图片描述
Service类封装业务流程(或者说是界面上的业务流程),DAO类封装对持久层的访问,DTO类封装业务实体对象。为什么要用Service接口和DAO接口?其实就是为了解耦,解耦说的意思是你更改某一层代码,不会影响我其他层代码。
Service + DAO,即DAO中只做CRUD及类似的简单操作(称之为功能点,不包含业务逻辑),Service中通过调用一个或多个DAO中的功能点来组合成为业务逻辑.Service的数量应该由功能模块来决定。在这种模型中业务逻辑是放在Service中的,事务的边界也应该在Service中控制.

以上,希望对你有所帮助。

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

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

相关文章

修改设备管理器的COM端口名称

Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class{4d36e978-e325-11ce-bfc1-08002be10318}\0001] “InfPath”“oem53.inf” “InfSection”“CH341SER_Inst.NTamd64” “ProviderName”“wch.cn” “DriverDateData”hex:00,00…

计算机算法(二)——进入计算机世界

作者介绍&#xff1a; &#x1f4de;作者&#xff1a;小刘在C站 &#x1f4c0;每天分享课堂笔记 &#x1f339;夕阳下&#xff0c;是最美的绽放 瑞士著名的科学家Niklaus Wirth教授曾提出&#xff1a;数据结构算法程序。 数据结构是程序的骨 算法是程序的灵魂。 在生活…

【 C++11 】lambda表达式

目录 1、lambda表达式的引入 2、lambda表达式 lambda表达式的语法 lambda表达式捕捉列表说明 使用lambda表达式排序自定义类型 lambda表达式的底层原理 1、lambda表达式的引入 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法&…

asp.net图书馆借阅归还系统

图书管理系统既是完整的知识定位系统&#xff0c;又是面向未来互联网发展的信息管理模式。图书管理系统&#xff0c;是一套利用计算机信息网络技术&#xff0c;实现对引用、注释和参考图书的自动化处理和规范化管理&#xff0c;服务于教师&#xff0c;学生及各类科研人员的集成…

【C语言进阶考试】你是否真正学懂了C语言

目录 前言 &#x1f392;选择题【全面深度剖析】 &#x1f4d7;考点一&#xff1a;无符号数unsigned的理解与应用 &#x1f4d5;考点二&#xff1a;字符ASCII计算与转换的理解和应用 &#x1f4d9;考点三&#xff1a;对位操作符的理解与应用 &#x1f4d8;考点四&#xf…

docker mysql 主从配置

准备&#xff1a;一台装有docker的虚拟机或者服务器 拉取mysql镜像&#xff1a; docker pull mysql:5.6 启动两个mysql容器 master docker run -p 1006:3306 --name mysql_master -v F:/mysql/mysql_master/conf:/etc/mysql -v F:/mysql/mysql_master/logs:/logs -v F:/mys…

【1024 | 程序员节】浅谈前端开发中常用的设计模式——适配器模式、工厂模式、单例模式等

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【前端面试专栏】 今天学习前端面试题相关的知识&#xff01; 感兴趣的小伙伴一起来看看吧~&#x1f91e; 文章目录设计模式设计模式分类工厂模式什么是工厂模式工厂模式好处单例模式…

I2C知识大全系列三 —— I2C驱动之单片机中的I2C

两种方式 单片机中的I2C驱动有两种方式。一种方式是用专用硬件I2C控制器实现&#xff0c;这种方式简单易行&#xff0c;品质也容易控制&#xff0c;只是会增加硬件成本方面的压力。另一种方式是用纯软件方式实现&#xff0c;这种方式几乎无硬件成本方面的考虑。 主要对比&…

网页图片采集-网页图片采集软件免费

一款免费的网页图片采集软件可以采集网页上的各种图片&#xff0c;每个人都可以采集到各种高清图源。支持任意格式的图片采集&#xff0c;只需要导入链接即可批量采集图片。 还有更多的采集方式&#xff1a;输入关键词全网图片采集/任意网站所有图片采集&#xff01;不仅可以采…

【C++】STL——vector(万字详解)

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…

记首次参加网络安全比赛(初赛-知识竞赛,决赛-CTF夺旗赛-解题模式)

网络安全相关的方向很多&#xff0c;几乎IT相关的安全内容都可以涵盖在内。笔者本身的知识体系更偏向于编程语言和Web应用&#xff0c;本次参赛可谓极具挑战&#xff0c;但是就是喜欢这种感觉&#xff1a;&#xff09; 赛程安排 9月16日接到通知 9月26日初赛 10月15日决赛 …

计算机网络习题答案

1、校园网属于&#xff08;局域网LAN &#xff09; 2、在下列传输介质中&#xff0c;(光缆 )传输介质的抗电磁干扰性最好。 3、光纤上采用的多路复用技术为&#xff08;WDM&#xff09; 4、计算机网络的交换方式不包括 无线交换 5、网络体系结构模型OSI模型和TCP/IP模型…

区块链实训教程(6)--开发、编译、部署、调用HelloWorld合约

文章目录1. 任务背景2. 任务目标3. 相关知识点4. 任务实操4.1 新建合约文件4.2 编写合约代码4.3 保存、编译、部署合约4.4 调用合约5. 任务总结1. 任务背景 FISCO BCOS运用智能合约进行归纳资产管理、规则定义和价值交换等操作&#xff0c;所以我们需要学习如何使用智能合约。…

aws ec2 配置jenkins和gitlab

环境搭建 下载jenkins的war包&#xff0c;启动jenkisn nohup java -jar jenkins.war --httpPort8091 > jenkins.log 2>&1 &docker安装gitlab 默认情况下&#xff0c;Omnibus GitLab 会自动为初始管理员用户账号 (root) 生成密码&#xff0c;并将其存储到 /etc…

HarmonyOS系统中内核实现温湿度采集方法

大家好&#xff0c;今天主要来聊一聊&#xff0c;如何使用鸿蒙系统中的温湿度传感器方法。 第一&#xff1a;温湿度传感器基本原理 大部分的传感器是在环境温度变化后会产生一个相应的延伸&#xff0c;因此传感器可以以不同的方式对这种反应进行信号转换。常见的大部分是电阻…

gitlab cicd 5分钟快速入门搭建私人代码仓库

gitlab 是企业级私有服务器 本文章采用docker搭建gitlab 如有不懂可微信我号yizheng369 环境准备 购买阿里云服务器&#xff0c;或者其他服务器 注意&#xff1a;本文章是用阿里云的centos 7.6作为服务器 搭建步骤 1.设置环境变量 export GITLAB_HOME/srv/gitlab2.编写dock…

今天面了个阿里拿27k出来的小哥,让我见识到了什么是天花板

2022年堪称大学生就业最难的一年&#xff0c;应届毕业生人数是1076万。失业率超50%&#xff01; 但是我观察到一个数据&#xff0c;那就是已经就业的毕业生中&#xff0c;计算机通信等行业最受毕业生欢迎&#xff01; 计算机IT行业薪资高&#xff0c;平均薪资是文科其他岗位的3…

PLC NAND 虽来但远

前言 图片来源&#xff1a; 存储随笔 2022年8月份在美国FMS峰会上&#xff0c;Solidigm公司(前身为 Intel NAND 部门) 展示了全球第一款基于PLC NAND研发的SSD。这也标志着&#xff0c;PLC时代已正式拉开序幕。出于对 PLC 的好奇&#xff0c;本文分享PLC NAND 知识&#xff0…

C/C++描述 - 矩阵乘积的计算

矩阵运算是现代科学及工程计算的基石之一&#xff0c;而矩阵乘法则是其中最常见一种运算。对于二维矩阵A、B&#xff0c;如果A的列数等于B的行数&#xff0c;则矩阵A、B可乘&#xff0c;其结果矩阵C的行数等于A的行数&#xff0c;列数等于B的列数。 本文引用自作者编写的下述图…

ArcGIS || ENVI:如何将彩色影像拆分为R、G、B以及H、S、I(B/V)影像?

目录 01 加载RGB影像数据 02 分别将三个波段进行保存 03 将RGB三色图像转化为HSI(HSB或者叫HSV)图像 04 转换的HSI图像拆分成H、S、I三个影像 首先&#xff0c;需要明确&#xff0c;手机拍摄的影像即是Red、Green、Blue三波段影像&#xff1b; 另外&#xff0c;由于方法十分…