【零基础入门MyBatis系列】第三篇——使用MyBatis完成CRUD
一、背景
1、什么是CRUD?
- 通常我们用CRUD代表增删改查四种操作。
- C:Create、R:Relative、U:Update、D:Delete。
2、在本篇内容学习之前,需要一些准备工作:
- 创建一个新的模块【利用Maven构建的普通Java模块】
- 修改 pom.xml 中的一些配置信息
- 添加一条语句,将打包方式定义为 jar 包 【因为我们当前不需要在web服务器上运行我们的项目】
- 添加 mybatis、mysql驱动、junit、logback的依赖
<!--打了一个jar包--><packaging>jar</packaging><dependencies><!--mybatis核心依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version><scope>import</scope></dependency><!--mysql驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version><scope>import</scope></dependency><!--添加junit依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!--导入日志文件的依赖--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version><scope>test</scope></dependency></dependencies>
- 将 mybatis-config.xml、logback.xml 文件 放到根路径下
(1) mybatis-config.xml 文件的配置信息如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--日志配置--><settings><setting name="logImpl" value="SLF4J"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><!--配置自己的数据库端口号和数据库--><property name="url" value="jdbc:mysql://localhost:3306/powernode"/><!--配置自己的数据库用户名和密码--><property name="username" value="root"/><property name="password" value="111111"/></dataSource></environment></environments><mappers><!--sql映射文件创建好之后,需要将该文件路径配置到这里[对应的Mapper文件]--><mapper resource="CarMapper.xml"/></mappers>
</configuration>
(2) logback.xml 文件的配置信息如下
<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名--><FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>30</MaxHistory></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder><!--日志文件最大的大小--><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>100MB</MaxFileSize></triggeringPolicy></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>
- 提供com.powernode.mybatis.utils.SqlSessionUtil工具类【方便创建会话】
package com.powernode.mybatis.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;/*** @author Bonbons* @version 1.0*/
public class SqlSessionUtil {private SqlSessionUtil(){}//定义一个SqlSessionprivate static final SqlSessionFactory sqlSessionFactory;//在类加载的时候初始化SqlSessionFactorystatic {try {//此处自己的 mybatis-config.xml 文件位置要配置正确sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));} catch (IOException e) {throw new RuntimeException(e);}}//通过一个公有的方法为外部提供会话的对象public static SqlSession openSession(){return sqlSessionFactory.openSession(true);}
}
- 最后一步就是创建测试用例
二、Insert【添加数据】
1、前情回顾:
- 之前我们的 CarMapper.xml 文件是这样写的:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace先随便写-->
<mapper namespace="car"><insert id="insertCar">insert into t_car(car_num,brand,guide_price,produce_time,car_type) values('103', '奔驰E300L', 50.3, '2022-01-01', '燃油车')</insert>
</mapper>
插入数据的语句是固定的,如果想插入不同的数据,只能在这块自己调整参数 >> 很不方便
2、改进方法1:
(1)在MyBatis中可以将数据放到Map集合中,在使用Java程序处理业务时,将Map对象作为参数传递进来。
(2)在sql语句中使用 #{map集合的key}
来完成传值,其中的 #{} 就是占位符
(3)给出改进后的 CarMapper.xml 中的配置信息【可以看出此时占位符中的参数已经替换为Map实例的key】
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先随意写一个-->
<mapper namespace="com.powernode.CarMapperTest"><!--insert sql:保存一个汽车信息--><insert id="insertCar">insert into t_car (id,car_num,brand,guide_price,produce_time,car_type) values (null,#{car_num},#{brand},#{guide_price},#{produce_time},#{car_type})</insert>
</mapper>
(4)再看一下测试用例中的代码:
@Test
public void testInsertCar(){//利用工具类创建会话SqlSession session = SqlSessionUtil.openSession();//创建一个Map存储我们要传递的信息Map<String, Object> map = new HashMap<String, Object>();// id,car_num,brand,guide_price,produce_time,car_type// 对于key的选取应该见名知意map.put("car_num", 3);map.put("brand", "奥迪");map.put("guide_price", 50.0);map.put("produce_time", "2022-10-18");map.put("car_type", "燃油车");//调用我们的添加方法session.insert("insertCar", map);//提交事务session.commit();session.close();
}
(5)运行后可以刷新 Navicat 查看结果
3、改进方法2:
(1)设置一个普通的Java类,类的属性对应数据库中的字段,为外部提供Get和Set方法【该系列将这种普通Java类称之为pojo】
(2)创建一个 com.powernode.pojo.Car 类,用于封装数据
package com.powernode.mybatis.pojo;/*** @author Bonbons* @version 1.0*/
public class Car {// id,car_num,brand,guide_price,produce_time,car_type// 使用包装类,出现null时不会报错// 对于这些私有属性要与表中数据对应上private Long id;private String carNum;private String brand;private Double guidePrice;private String produceTime;private String carType;//提供构造方法public Car(){}public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {this.id = id;this.carNum = carNum;this.brand = brand;this.guidePrice = guidePrice;this.produceTime = produceTime;this.carType = carType;}//提供get和set方法public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getCarNum() {return carNum;}public void setCarNum(String carNum) {this.carNum = carNum;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Double getGuidePrice() {return guidePrice;}public void setGuidePrice(Double guidePrice) {this.guidePrice = guidePrice;}public String getProduceTime() {return produceTime;}public void setProduceTime(String produceTime) {this.produceTime = produceTime;}public String getCarType() {return carType;}public void setCarType(String carType) {this.carType = carType;}//重写toString方法@Overridepublic String toString() {return "Car{" +"id=" + id +", carNum='" + carNum + '\'' +", brand='" + brand + '\'' +", guidePrice=" + guidePrice +", produceTime='" + produceTime + '\'' +", carType='" + carType + '\'' +'}';}
}
(2)要修改 CarMapper.xml 文件,更改 insert 方法中占位符中的内容
- 这里面需要注意一个问题,占位符中的内容并不一定是Car类中的参数,它这个对应机制是这样的:
#{parameter} --> getParemeter() 【也就是说会去Car类中寻找这个get方法来获取参数】
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先随意写一个-->
<mapper namespace="com.powernode.CarMapperTest"><!--insert sql:保存一个汽车信息--><insert id="insertCar">insert into t_car (id,car_num,brand,guide_price,produce_time,car_type) values (null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})</insert>
</mapper>
(3)原来的测试类中添加相关的的测试方法
@Test
public void testInsertCarByPOJO(){SqlSession session = SqlSessionUtil.openSession();//封装数据Car car = new Car(null, "4", "托马斯", 200.0, "2022-11-11","煤油车");//事务处理session.insert("insertCar", car);//提交事务session.commit();session.close();
}
4、总结
- 如果采用map集合传参,#{} 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL。
- 如果采用POJO传参,#{} 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写【getAge对应的是 #{age}】
三、delete 和 update【删除、更新数据】
- 此处我们只涉及简单的删除和更新操作,重点在于了解基本语法
- 我们根据 id 来完成数据的删除和更新
- 此部分给出在 CarMapper.xml 中的配置信息以及测试类中的对应测试方法
1、通过指定 id 删除数据
(1)在CarMapper.xml 中的配置信息如下【为了看起来更简洁,只给出对应的SQL语句】
- 有一件值得注意的事情:当只存在一个占位符时,可以自动识别,参数名不匹配也没有问题
<!--根据id删除数据-->
<delete id="deleteById">delete from t_car where id = #{id}
</delete>
它的外部代码是这样的
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="balabala">
<!--在这部分写我们的SQL语句-->
</mapper>
(2)测试方法如下【也是只给出了完整方法,没去写类名】
@Test
public void testDeleteCarById(){SqlSession sqlSession = SqlSessionUtil.openSession();// count会记录操作实际影响数据库表中数据的条数int count = sqlSession.delete("deleteById", 15);//通过变量名.sout 可以快速生成输出指定变量的语句[在IDEA中]System.out.println(count);sqlSession.commit();sqlSession.close();
}
(3)成功运行,删除了原来 id = 15 的数据
2、通过指定 id 更新数据
(1)在CarMapper.xml 中的配置信息如下
<!--根据id修改数据-->
<update id="updateById">update t_car set car_num = #{carNum}, brand = #{brand}, guide_price = #{guidePrice}, produce_time = #{produceTime},car_type = #{carType} where id = #{id}
</update>
(2)测试方法如下
@Test
public void testUpdateCarById(){SqlSession sqlSession = SqlSessionUtil.openSession();Car car = new Car(17L, "1111", "奔驰大G", 200.0, "2020-01-01", "汽油越野车");int count = sqlSession.update("updateById", car);System.out.println(count);sqlSession.commit();sqlSession.close();
}
(3)成功运行,修改了原来 id = 17 的数据
四、Select【查询数据】
- 查询语句的重点在于:对于查询结果集的处理以及类属性名与数据库字段名的对应
- 此处分别以查询一条数据和查询全部数据为例,来说明MyBatis中是如何完成数据查询的
1、 根据 id 查询一条数据:
(1)CarMapper中的配置信息
<select id="selectById" resultType="com.powernode.mybatis.pojo.Car"><!--select * from t_car where id = #{id}-->select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car where id = #{id}
</select>
细心的盆友不难发现,查询语句与其他数据操作SQL语句不同:
第一,多了resultType;第二为查询的字段设置了别名
- 使用 resultType 是为了告诉 MyBatis 我们查询结果集是一个什么类型的数据【使用的是全限定类名(类的完整地址)】
- 设置别名,是因为如果类属性与数据库表中字段对应不上,就无法正确传递参数值
(2)测试方法
@Test
public void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();//用Car的实例接收返回值Car car = sqlSession.selectOne("selectById",1);//打印查询结果[之所以此处可以输出属性和值,是因为在Car类中重写了toString方法]System.out.println(car);//查询语句不需要提交事务sqlSession.close();
}
2、查询全部的数据
- 与前者的区别在于:查询时不需要设置条件、返回的是一个结果的集合
(1)CarMapper中的配置信息
<!--查询数据库表中全部数据-->
<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car
</select>
(2)测试方法
@Test
public void testSelectAll(){SqlSession sqlSession = SqlSessionUtil.openSession();List<Car> cars = sqlSession.selectList("selectAll");//使用Lamda表达式+forEach输出cars.forEach(car -> System.out.println(car));sqlSession.close();
}
3、namespace 用法说明
- 当出现两个 XxxMapper.xml 文件中出现同ID的SQL语句时,可能会出现问题
- 我们可以通过
namespace.SQL语句id
来指定使用哪个Mapper中的 SQL 方法 - 简言之,命名空间 >> 防止 id 冲突
- PS:如果设置了多个Mapper.xml 文件,要记得添加到核心配置文件中
【零基础入门MyBatis系列】第三篇——使用MyBatis完成CRUD相关推荐
- 零基础入门网络安全,收藏这篇不迷茫【2023 最新】
零基础入门网络安全,收藏这篇不迷茫[2023 最新] 前言 最近收到不少关注朋友的私信和留言,大多数都是零基础小友入门网络安全,·需要相关资源学习.其实看过的铁粉都知道,之前的文里是有过推荐过的.新来 ...
- 【零基础入门前端系列】—背景属性(十二)
[零基础入门前端系列]-背景属性(十二) 一.背景属性 CSS背景属性主要有以下几个: CSS3中可以通过background-image属性添加背景图片. 不同的背景图像和图像用逗号隔开,所有的图片 ...
- 视频教程-ARDUINO零基础入门教程【代码编程篇】-Arduino
ARDUINO零基础入门教程[代码编程篇] 精通各种单片机编程,有十年以上ARDUINO,51单片机/STM32/PIC/AVR编程,硬件设计,绘图,编程经验.熟悉各种常用传感器使用和物联网通讯 赵勇 ...
- 生日祝福小程序_广告配音剪映零基础入门教程第二十六篇:如何给朋友制作生日祝福视频...
经常听到小伙伴问到生日祝福视频怎么做,当然我想既然要为他人做生日祝福视频,那么这个人必定是自己身边比较重要的人,而生日又是每个人都是非常重要的,在这种充满意义的时刻,我们想给自己极其重要的人送上一份祝 ...
- 零基础入门STM32编程(三)
前情回顾 通过前面两篇文章的学习,我们已经对STM32有了一定的了解,知道了STM32单片机的基本分类和不同产品间的特点等知识,今天起围绕STM32F103xx继续深入浅出地学习单片机编程. 一.总线 ...
- 零基础入门深度学习的五篇经典教程
零基础入门深度学习>系列文章旨在讲帮助爱编程的你从零基础达到入门级水平.零基础意味着你不需要太多的数学知识,只要会写程序就行了,没错,这是专门为程序员写的文章.虽然文中会有很多公式你也许看不懂, ...
- 神仙级python入门教程(非常详细)零基础入门到精通看这篇开始
▌▌ Python的应用 自动化工具:自动处理数据.Excel文件.发邮件.下载.上传数据 网络爬虫:代替人工自动从下载数据,例如:商品信息.股票数据.技术文章 Web网站:开发一个网站.APP.小程 ...
- Vue全家桶学习笔记_零基础入门到入坑:Vue篇
文章目录 前言 什么是Vue,什么又是框架 完善的准备 Vue 引入 npm 安装 cnpm镜像加速器 安装 Vue-Cli脚手架 安装 webpack 安装 webpack-cli 安装 axios ...
- 尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版(三)
EL表达式 什么是EL表达式 <%@ page contentType="text/html;charset=UTF-8" language="java" ...
- 零基础入门JAVAweb——前端开发html篇
最新文章
- Python技术分享:ndarray对象的常用属性
- C和指针之动态内存分配堆、栈、全局区(静态区)、常量区对比总结学习笔记
- Linux下文件的多进程拷贝
- python字符串数组_python将字符串转换成数组的方法
- 浏览器弹窗怎么设置显示url_谷歌浏览器Chrome76版本地址栏不显示HTTPS和WWW怎么办?...
- 程序员误区1:软件开发职业是青春饭
- 用条件运算符编写java程序_Java 编程入门课程丨第 8 单元:条件运算符和控制语句...
- 自定义控件常用方法总结
- java数组怎么添加元素_Java封装数组之添加元素操作实例分析
- python (continue与break)区别
- php生成透明png图像 无锯齿
- win7计算机怎么录屏,怎么用win7系统的电脑录屏
- Nifi从入门到精通(一)之 数据存储
- java实现商品的分类_Spring 商品分类
- 【预测师】的时间管理方法论(泰山版)
- 关于ZBRUSH弯折功能使用问题
- keep sb updated_keep me updated是什么意思
- 命令行窗口的解释及使用
- 非递归实现二叉树的遍历
- springcloud 项目maven依赖:Failure to find org.springframework.cloud:spring-cloud-dependencies
热门文章
- 翻译狗文档免费下载手册(补充版)
- hexo WARN No layout: index.html
- git、githut、码云概念和使用,md文件编辑,
- android 国家代码
- php tracert,详解路由跟踪命令(tracert)
- python保存对话框_python打开文件对话框的方法
- ThinkPHP3.2.3实现后台登录界面
- android 动态仿磁贴,UWP开发:给App加上动态磁贴
- 稻盛和夫自传读书笔记
- 服务器双系统快捷键,mac双系统切换快捷键