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

news/2024/11/24 1:50:54/

目录

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=falseusename: rootpassword: 123456driver-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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate UserMapper userMapper; //把我们需要测试的方法的类注入过来@Testvoid 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已经帮我们映射好了.

进行单元测试

 @Testvoid 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 // 事务 加了此注解单元测试就不会污染数据库了@Testvoid 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@Testvoid 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>

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

单元测试

 @Testvoid 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属性

单元测试

@Testvoid 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为"白",在数据库里面看到的会是:'%'白'%',占位符会自动添加双引号,所以我们这里用字符串拼接的方式

单元测试

@Testvoid 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字段
我们想要映射几个属性和字段,就需要写几个

单元测试

  @Testvoid 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.ppmy.cn/news/124305.html

相关文章

记一次k8s节点上出现node.kubernetes.io/disk-pressure污点的问题

目录 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 其他问题 问题描述 k8s部署时pod一直属于Pending状态&#xff0c;也就是说pod未调度到k8s节点上 原因分析&#xff1a; 通过以下命令查看下pod kubectl get pod 以上命令可以看到各个pod的状态&#xff0c…

日立真空冰箱R-ZXC750KC,智启行业保鲜新生态

“小扇引微凉&#xff0c;悠悠夏日长”&#xff0c;仲夏六月&#xff0c;日立冰箱正式开启“年中盛典”618新鲜季活动。天猫日立电器旗舰店除超值钜惠、精致好礼之外&#xff0c;更有更令人心动的消费补贴、买1送1等福利&#xff0c;这个夏天&#xff0c;想要家电焕新的小伙伴们…

科技创新与设计美学共铸高端,三星品道家宴系列冰箱即将上线

近年来&#xff0c;随着高净值群体的发展壮大&#xff0c;追求“品质”与“高端”的消费观念成为新趋势&#xff0c;从而驱动了各行各业快速升级创新&#xff0c;其中就包括冰箱行业。在冰箱行业&#xff0c;三星冰箱凭借顶尖的保鲜技术、精妙的内部设计和高质感的外观工艺&…

云米冰箱能控制扫地机器人_在云米的大屏冰箱就能操控其他智能家电?一起到京东618了解更多...

还值得一提的是&#xff0c;当你在煮菜的过程中发现有某样食物忘记购买的时候&#xff0c;你并不需要自己下楼去购买&#xff0c;在这个21寸屏幕上就可以完成购物的需求。云米联合诸多巨头&#xff0c;为消费者提供丰富的产品新鲜的蔬菜、新鲜的生鲜、粮油副食、肉类、水果等等…

高端智能冰箱成白电市场新宠,营造品质生活方式为上策

作为家中的必须生活家电&#xff0c;整体冰箱行业正处在一个转型变革的时间节点上。而到了当下&#xff0c;高端、智能成为国内冰箱领域的两大关键词&#xff0c;正是凭借于此&#xff0c;冰箱再度突破发展束缚&#xff0c;成为白电市场新宠。 现实中&#xff0c;三星的冰箱就…

不忘初心,TCL冰箱洗衣机20周年从心出发

心无界行无疆&#xff0c;一切伟大源于敢想&#xff0c;“当心不再受到束缚&#xff0c;不再设有限制&#xff0c;那么成长的空间将无限大”2018年8月8日&#xff0c;心无界-2018TCL冰箱洗衣机全球战略合作伙伴大会在安徽合肥盛大开幕。来自全球的TCL冰箱洗衣机战略合作伙伴汇集…

冰箱堪比「垃圾桶」?这根棒除味又保鲜,更能 99% 超强杀菌!

{} ▲ 点击查看 每天的饭菜、生鲜、零食、饮料、干货&#xff0c;总能把我家冰箱塞得满满当当。 各种饭菜干货窜味儿&#xff0c;蔬果开始发烂发臭&#xff0c;每天打开冰箱都是一次「开门杀」…… 用柚子皮和竹炭包除味根本不行&#xff0c;从根源上改善冰箱环境才是硬道理。 …

小程序

小程序 三、微信公众平台 开发者通过公众号向用户提供咨询和服务的平台&#xff01;&#xff01;&#xff01; Mp.weixin.qq.com 账号分类 订阅号、服务号、企业微信、小程序&#xff08;小游戏&#xff09;  订阅号 订阅号&#xff1a;为媒体和个人提供一种新的信息传播方…