MyBatis(MyBatis环境搭建,单表操作)

news2024/11/16 9:54:40

目录

MyBatis 环境搭建

 1.添加 Mybatis 框架支持

2.设置 MyBatis 配置信息

2.1.设置数据库连接的相关信息

2.2 Mybatis xml 保存路径和 xml命名格式

​编辑 MyBatis 模式开发

Mybatis xml 模板

查询表内容

单元测试

以根据id,查询用户对象这个方法为例

 获取动态参数的俩种方式 ${param} #{param}

${param}

 #{param}

各种MyBatis单表操作

如果传递的参数为一个对象,如何获取对象里面的属性?

 用户的修改

删除用户

添加用户

1.返回值为受影响行数

​编辑2.返回受影响的行数和id

根据用户名模糊查询

返回字典映射 resultMap


什么是MyBatis?:更加简单的帮助程序实现数据库操作的工具

MyBatis 环境搭建

 1.添加 Mybatis 框架支持

MyBatis项目不仅要添加MyBatis Framework的依赖,还要添加添加MySql Driver依赖(用于指定连接数据库的类型,这里我们使用MySql数据库,所以需要引入MySql Driver依赖,如果是别的类型数据库类型同理,比如使用MariaDB数据库,此处就可以引用MariaDB Driver依赖)

2.设置 MyBatis 配置信息

2.1.设置数据库连接的相关信息

在配置文件中配置如下信息

#设置数据库连接信息
spring:
  datasource:
    url:  jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
    usename: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

2.2 Mybatis xml 保存路径和 xml命名格式

mybatis:
  mapper-locations: classpath:/mybatis/*Mapper.xml

这里交代了Mybatis xml的保存路径,在本地一个叫mybatis包底下,后缀为Mapper.xml的文件

 MyBatis 模式开发

1. interface: 让其他层可以注入使用的接口

2.mybatis: xml 具体实现sql(它是上述interface的实现)

Mybatis xml 模板

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
   
</mapper>

注意这里的namespace表示当前xml实现的类是哪个类,这里就表示当前xml实现的类是UserMapper这个类

查询表内容

以实现查询操作为例,现在有一个mycnblog数据库,里面有一张用户表(userinfo)

表里的内容如下

.
这张表映射到Java中的UserEntity的实体类如下 

@Data
public class UserEntity {
    private Integer id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private Integer state;
}

首先实现实现一个MyBatis的接口

@Mapper//表示这是一个Mybatis接口,需要和xml对应起来
public interface UserMapper {
    List<UserEntity> getAll();
}

 实现这个接口对应的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="getAll" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo
    </select>
</mapper>

此处我们需要进行查询操作,所以需要使用select标签,同理如果是添加操作.需要使用insert标签
此处的id,是我们要实现的这个类里面的某个方法的方法名
此处的resultType是我们要返回的数据类型

使用service层调用该接口

import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public List<UserEntity> getAll(){
        return userMapper.getAll();
    }
}

使用controller调用service层的接口

package com.example.demo.controller;

import com.example.demo.entity.UserEntity;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("getAll")
    public List<UserEntity> getAll(){
        return userService.getAll();
    }
}

我们此时在网页中访问这个getAll方法

 上述测试getAll方法的过程比较繁琐,需要调用controller层,service层.且如果测试的是修改,添加等方法也会污染数据库.所以接下来我们使用单元测试的方法

单元测试

单元测试优点

1.可以非常简单,直观,快速的测试某一个功能是否正确

2.使用单元测试可以帮助我们在快速打包时发现一些问题,在打包之前,所有的单元测试必须通过,否则不能打包成功

3.使用单元测试在测试功能的时候,不污染连接的数据库,可以不对数据库进行任何改变的情况下,测试功能

4.可以跳过系统限制(登录校验,权限检验),直接测试想要测试的方法

SpringBoot项目会默认自带一个单元测试的框架(由JUnit实现),咱们直接用就好了

以根据id,查询用户对象这个方法为例

同样实现一个mapper接口

@Mapper//表示这是一个Mybatis接口,需要和xml对应起来
public interface UserMapper {
    List<UserEntity> getAll();
    //根据id 查询用户对象
    UserEntity getUserById(@Param("id")Integer id);
}

这里的@Param("id"),意思是给这个叫做id的参数,重新起了个叫id的名字,之后在xml中,就以Param里面的名字为准

实现这个接口对应的xml

<select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id = ${id}
    </select>

这里 id = ${id} 左边的"="号左边的id是数据库userinfo表里面的叫id的字段,右边的id就是我们之前在mapper接口传入的参数id,这里使用${}的方式是为了获取到属性中的id的值,如果直接写id=id,那么左边的id拿到的就是id这个字符串,而不是传入给id的值.

在我们想要测试的方法上右键生成

点击Test,勾中我们想要测试的方法

 会在test底下和main一样的包路径下,生成一个Test的类,里面有我们要测试的方法

此时我们需要在这个自动生成的类 添加一些注解@SpringBootTest

@SpringBootTest // 表示当前单元测试的类是运行在 SpringBoot 环境中的
class UserMapperTest {
    @Autowired
    private UserMapper userMapper; //把我们需要测试的方法的类注入过来
    @Test
    void getUserById() {
        UserEntity user = userMapper.getUserById(1);
        System.out.println(user);
    }
}

点击此处运行该方法 

 在控制台有我们输出的user打印信息,测试成功

 获取动态参数的俩种方式 ${param} #{param}

${param}

把${param}直接替换成传过来的参数,所见即所得,比如如果我们需要的参数是字符类型,这种获取参数的方式默认是没有字符需要的引号的.且这种方式会出现sql注入的问题,容易出现安全性问题,适用于我们需要传递一些sql指令的场景(如传递排序方式),在使用时,我们需要保证我们输入的值可以被枚举(保证不被sql注入).

 #{param}

把#{param}用一个占位符代替,再把参数传给这个占位符,是预处理

各种MyBatis单表操作

如果传递的参数为一个对象,如何获取对象里面的属性?

例如实现一个登录的方法

mapper接口

@Mapper//表示这是一个Mybatis接口,需要和xml对应起来
public interface UserMapper {
    //根据名称查询用户对象
    UserEntity login(UserEntity user);
}

xml

<select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username = #{username} and password = #{password}
    </select>

这里我们没有使用user.getUserName的方式获取username,而是直接输入username,password原因是MyBatis已经帮我们映射好了.

进行单元测试

 @Test
    void getUserByName() {
        UserEntity userLogin = new UserEntity();
        userLogin.setUsername("admin");
        userLogin.setPassword("admin");
        UserEntity user = userMapper.login(userLogin);
        System.out.println(user);
    }

 用户的修改

修改用户密码

mapper接口

//修改密码  返回值为受影响的行数
    int updatePassword(@Param("id") Integer id,
                       @Param("password") String password,
                       @Param("newPassword")String newPassword);

xml

<update id="updatePassword">
    update userinfo set password = #{newPassword} where id = #{id} and password=#{password}
</update>

update标签设置一个参数就可以了,不需要设置返回值,当使用upadate标签时,默认会返回一个受影响的行数,不需要再设置了

单元测试

 @Transactional // 事务 加了此注解单元测试就不会污染数据库了
 @Test
    void updatePassword() {
        int result = userMapper.updatePassword(1,"admin","123456");
        UserEntity user = userMapper.getUserById(1);
        System.out.println("修改  "+result);
        System.out.println(user);
    }

删除用户

mapper接口

//删除用户
    int delById(@Param("id") Integer id);

xml

<delete id="delById">
        delete from userinfo where id = #{id}
    </delete>

使用delete标签来进行删除操作,和修改操作一样,delete标签不需要设置返回值,默认返回值是int,受影响的行数

单元测试

 @Transactional
    @Test
    void delById() {
        int result = userMapper.delById(1);
        UserEntity user = userMapper.getUserById(1);
        System.out.println("删除 "+result);
        System.out.println(user);
    }

添加用户

1.返回值为受影响行数

mapper接口

 //添加用户
    int addUser(UserEntity user);

 xml

<insert id="addUser">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>

同样,当我们返回值是受影响行数时,不需要设置返回值

单元测试

 @Test
    void addUser() {
        UserEntity user = new UserEntity();
        user.setUsername("白杨");
        user.setPassword("123456");
        int result = userMapper.addUser(user);
        UserEntity user2 = userMapper.getUserByName("白杨");
        System.out.println(result);
        System.out.println(user2);
    }


2.返回受影响的行数和id

mapper接口

int addUserGetId(UserEntity user);

xml

<insert id="addUserGetId" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>

 useGeneratedKeys为是否要拿到数据库自增的id,keyProperty = id 为把刚刚拿到的id赋值给userinfo对象中的id属性

单元测试

@Test
    void addUserGetId() {
        UserEntity user = new UserEntity();
        user.setUsername("杰尼龟");
        user.setPassword("123456");
        int result = userMapper.addUserGetId(user);
        UserEntity user2 = userMapper.getUserByName("杰尼龟");
        System.out.println(result);
        System.out.println(user2);
        System.out.println(user.getId());
    }

 

注意在单元测试代码中,我们并没有给user的id属性赋值,而执行流addUserGetId方法后,我们却能拿到Id,这就是  useGeneratedKeys和keyProperty的作用了

根据用户名模糊查询

mapper接口

 //根据用户名模糊查询
    List<UserEntity> getListByName(@Param("username")String username);

xml

<select id="getListByName" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username like concat('%','#{username}','%')
    </select>

使用concat字符串拼接,如果写成'%#{username}%',此时如果传入的username为"白",在数据库里面看到的会是:'%'白'%',占位符会自动添加双引号,所以我们这里用字符串拼接的方式

单元测试

@Test
    void getListByName() {
        String username = "白";
        List<UserEntity> list = userMapper.getListByName(username);
        list.stream().forEach(System.out::println);
    }

返回字典映射 resultMap

使用场景:字段名称和程序中的属性名不同,可以使用 resultMap 配置映射
一对一和一对多关系可以使用 resultMap 映射并查询数据库

例如当我们程序中UserEntity这个类映射数据库userinfo这张表时,UserEntity的属性名为pwd,而userinfo的字段名为password

@Data
public class UserEntity {
    private Integer id;
    private String username;
    private String pwd;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private Integer state;
}

userinfo表内容

同样以根据用户名模糊查询这个方法为例

mapper接口

//根据用户名模糊查询
    List<UserEntity> getListByName(@Param("username")String username);

xml

 <resultMap id="BaseMap" type="com.example.demo.entity.UserEntity">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="pwd" column="password"></result>
    </resultMap>
    <select id="getListByName" resultMap="BaseMap">
        select * from userinfo where username like concat('%',#{username},'%')
    </select>

id="BaseMap"表示给当前resultMap字典起了个叫BaseMap的名字,type表示当前这个resultMap这个字典,用来映射哪个实体类 
<id></id>这里面放的是主键  property = "id",column = "id"意思是程序中的属性id对应数据库中的id字段
<result></result>放的是普通的字段 property = "pwd" column = "password"意思是程序中的属性 pwd,对应数据库中的password字段
我们想要映射几个属性和字段,就需要写几个

单元测试

  @Test
    void getListByName() {
        String username = "白";
        List<UserEntity> list = userMapper.getListByName(username);
        list.stream().forEach(System.out::println);
    }

 当然上述方法可能有点繁琐,我们也可以通过调整sql语句实现这种功能(通过as重命名)

xml:

  <select id="getListByName" resultType="com.example.demo.entity.UserEntity">
        select id,username,password as pwd from userinfo where username like concat('%',#{username},'%')
    </select>

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

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

相关文章

警惕,最近的副业兼职诈骗。

大家好&#xff0c;我是鸟哥。 今天和大家聊聊最近超级猖狂的几类诈骗。 一、副业诈骗。最近两年“副业刚需”这个口号很流行&#xff0c;尤其是今年&#xff0c;职场动荡、工作难找&#xff0c;副业刚需变成了副业焦虑&#xff0c;骗子们也正是抓住了大家的这个心理&#xf…

【Vue全家桶实现电商系统】— VSCode配置Git(二)

【Vue全家桶实现电商系统】— VSCode配置Git&#xff08;二&#xff09; 当我们在VScode中编写代码后&#xff0c;需要提交到git仓库时&#xff0c;但是我们又不想切换到git的命令行窗口&#xff0c;我们可以在 VScode中配置git&#xff0c;然后就可以很方便快捷的把代码提交…

JavaScript中的Hook技术:特性、优点、缺点和使用场景

引言&#xff1a; 随着JavaScript的不断发展&#xff0c;开发者们正在寻找更灵活和可扩展的方式来修改或扩展现有的代码。其中一种广泛应用的技术是"Hook"&#xff0c;它允许开发者拦截和修改现有的函数或方法的行为。本文将详细介绍JavaScript中的Hook技术&#xf…

软件确认测试、验收测试和系统测试有什么区别和联系?

软件确认测试、验收测试和系统测试都是软件测试过程中的重要环节&#xff0c;它们各自有不同的测试侧重点和目标&#xff0c;但也有一些联系。 1、软件确认测试 称为单元测试或白盒测试&#xff0c;是对软件中各个模块的基本功能进行测试的一种测试方式&#xff0c;主要使用…

【Python从入门到进阶】22、urllib库基本使用

接上篇《21、爬虫相关概念介绍》 上一篇我们介绍了爬虫的相关概念&#xff0c;本篇我们来介绍一下用Python实现爬虫的必备基础&#xff0c;urllib库的学习。 一、Python库的概念 我们今后的学习可能需要用到很多python库&#xff08;library&#xff09;&#xff0c;及引用其…

在阿里外包干了3个月,我果断跑路了

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

Python接口自动化脚本持续集成过程

之前都是开发人员提交代码到git&#xff0c;触发jenkins拉取git上面的代码并进行编译部署&#xff0c;部署成功后测试人员就可以在浏览器端开始测试了。 作为测试人员&#xff0c;也有跟git和jenkins打交道的时候。 项目实践&#xff1a; python接口自动化脚本编写成功后&am…

图解LeetCode——102. 二叉树的层序遍历

一、题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 二、示例 2.1> 示例 1&#xff1a; 【输入】root [3,9,20,null,null,15,7] 【输出】[[3],[9,20],[15,7]] 2.2> 示例…

Redis7实战加面试题-高阶篇(手写Redis分布式锁)

手写Redis分布式锁 面试题&#xff1a; 1.Redis除了拿来做缓存&#xff0c;你还见过基于Redis的什么用法? 数据共享&#xff0c;分布式session分布式锁 全局ID 计算器、点赞位统计 购物车 轻量级消息队列&#xff08;list&#xff0c;stream&#xff09; 抽奖 点赞、签到、打…

功率信号源驱动电路工作原理是什么

功率信号源驱动电路是一种能够将低功率、微弱的信号放大到足够高的功率水平的电路。在现代通信、医疗、工业等领域中&#xff0c;功率信号源驱动电路被广泛应用。下面&#xff0c;我们将对功率信号源驱动电路进行详细的介绍。 图&#xff1a;ATG-2000系列功率信号源 功率信号源…

【大数据学习篇12】 Spark项目实战-数据可视化

学习目标/Target 了解数据可视化系统架构 掌握Phoenix集成HBase 熟悉建立Phoenix与HBase表映射 了解Spring Boot项目的创建 掌握Java Web项目中实体类的创建 掌握Java Web项目中数据库访问接口的创建 掌握Java Web项目中控制器类的创建 熟悉Java Web项目中HTML页面的创建…

23种设计模式之模板方法模式(Template Method Pattern)

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将23种设计模式中的模板方法模式&#xff0c;此篇文章为一天学习一个设计模式系列文章&#xff0c;后面会分享其他模式知识。 如果文章有什么需要改进的地方还请大…

第十九章行为型模式—中介者模式

文章目录 中介者模式解决的问题结构实例存在的问题适用场景 中介者模式和代理模式的区别代理模式中介模式桥接模式总结 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务&#xff0c;它涉及算法…

day0 -- Mysql专业名词认识部分

数据库(database)/资料库 常见的数据库/资料库且以物理形式存在的&#xff0c;比如图书馆&#xff0c;再比如书柜。 是一种有组织的存放资料/数据的容器。 数据库管理系统(DBMS) 创建数据库和管理数据库的系统&#xff0c;可以对数据库进行组织、管理、访问、修改等操作的一套…

真的被00后卷麻了,还好我很会划水~

前情提要 鉴于目前测试就业越来越严峻&#xff0c;内卷也成了测试领域的代名词了。我的一个HR朋友告诉我&#xff0c;现在测试岗的投递比已经将近1000&#xff0c;也就是一个岗位差不多有千份简历投进来&#xff0c;实在是恐怖&#xff01; 前段时间我也去面试了一些公司&…

C4D 必备的 7 个素材网站!

C4D近几年来是一个非常热门的专业/职业&#xff0c;特别是在建模行业大多数时候都会选择使用C4D进行&#xff0c;相信也有很多粉丝朋友喜欢C4D这个类别。 但是我在一些网站上&#xff0c;经常会看到有人说想要一些C4D的素材&#xff0c;但是不知道去哪里找&#xff0c;也不知道…

redis 数据结构String之SDS

redis字符串(String)内存结构&#xff1a; 字符串对象底层数据结构实现为简单动态字符串&#xff08;SDS&#xff09;和直接存储&#xff0c;但其编码方式可以是int、raw或者embstr&#xff0c;区别在于内存结构的不同。 int编码 字符串保存的是整数值&#xff0c;并且这个正式…

iOS 16 UI 设计系统免费在线使用方法

1、iOS 16 UI 设计系统中有什么&#xff1f; iOS 16 UI 设计系统通常包含以下组件和元素&#xff1a; 1. 按钮&#xff1a;包括操作按钮、图标按钮、导航按钮、滚动按钮、切换按钮、单选按钮、复选框按钮、呼叫按钮等各种类型的按钮。 2. 窗口和 UI 控件&#xff1a;包括标签…

JAVA变量在不同情况下未赋值与默认初始值

目录 一、默认初始值 二、本地变量 代码 运行结果 二、实例变量 代码 运行结果 三、本地变量和实例变量的区别 1.作用域 2.生命周期 3.初始化 一、默认初始值 数据类型初始值数据类型初始值byte0long0Lchar‘u0000’float0.0fshort0double0.0int0booleanfalse引用nul…

人工智能-机器学习人工神经网络

机器学习 机器学习部分主要学习的内容是朴素贝叶斯算法和决策树算法。 决策树算法 决策树算法是机器学习中常用的一种分类算法&#xff0c;在决策树中&#xff0c;使用各个属性进行分类&#xff0c;选取每次分类的属性的方式有多种。最简单的是ID3算法&#xff0c;使用信息增…