MyBatis(三)使用MyBatis完成CRUD(增删改查)

news2024/11/20 7:15:43

准备工作

1、创建module(Maven的普通Java模块):mybatis-002-crud

2、pom.xml

  • 打包方式jar
  • 依赖:
  • mybatis依赖
  • mysql驱动依赖
  • junit依赖
  • logback依赖

3、mybatis-config.xml放在类的根路径下

4、CarMapper.xml放在类的根路径下

5、logback.xml放在类的根路径下

6、提供com.powernode.mybatis.utils.SqlSessionUtil工具类

7、创建测试用例:com.powernode.mybatis.CarMapperTest

一、insert(Create)增

分析以下SQL映射文件中SQL语句存在的问题:CarMapper.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">
<!--namespace先随意写一个-->
<mapper namespace="insertCar">
    <!--insert sql:保存一个汽车信息-->
    <insert id="insertCar">
        insert into t_car
            (id,car_num,brand,guide_price,produce_time,car_type)
        values
            (null,'133','名爵-7',12.34,'2023-10-15','氢能源')
    </insert>
</mapper>

存在的问题是:SQL语句中的值不应该写死,值应该是用户提供的。之前的JDBC代码是这样写的:

JDBC:

// JDBC中使用 ? 作为占位符。那么MyBatis中会使用什么作为占位符呢?
String sql = "insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(?,?,?,?,?)";
// ......
// 给 ? 传值。那么MyBatis中应该怎么传值呢?
ps.setString(1,"103");
ps.setString(2,"奔驰E300L");
ps.setDouble(3,50.3);
ps.setString(4,"2022-01-01");
ps.setString(5,"燃油车");

在MyBatis中:

在Java程序中,将数据放到Map集合中

在sql语句中使用 #{map集合的key} 来完成传值,#{} 等同于JDBC中的 ? ,#{}就是占位符

Java程序这样写:

1、CarMapperTest.testInsertCar测试类中:

package com.powernode.mybatis.test;

import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
 * @author wuw
 * @since 2023-02-01 14:14:58
 */
public class CarMapperTest {
    @Test
    public void testInsertCar(){
        // 准备数据
        Map<String, Object> map = new HashMap<>();
        map.put("k1", "103");
        map.put("k2", "奔驰E300L");
        map.put("k3", 50.3);
        map.put("k4", "2020-10-01");
        map.put("k5", "燃油车");
        // 获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 执行SQL语句(使用map集合给sql语句传递数据)
        int count = sqlSession.insert("insertCar", map);
        System.out.println("插入了几条记录:" + count);
    }
}

2、CarMapper.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">

<!--namespace先随便写-->
<mapper namespace="car">
    <insert id="insertCar">
        insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{k1},#{k2},#{k3},#{k4},#{k5})
    </insert>
</mapper>

#{} 的里面必须填写map集合的key,不能随便写,否则获取不到值,数据库的值将变成null。

3、运行测试程序,查看数据库:

 

在以上sql语句中,可以看到#{k1} #{k2} #{k3} #{k4} #{k5}的可读性太差,为了增强可读性,我们可以将Java程序做如下修改:

优化版1:

测试类中:CarMapperTest.testInsertCar

Map<String, Object> map = new HashMap<>();
// 让key的可读性增强
map.put("carNum", "103");
map.put("brand", "奔驰E300L");
map.put("guidePrice", 50.3);
map.put("produceTime", "2020-10-01");
map.put("carType", "燃油车");

CarMapper.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="car">
    <insert id="insertCar">
        insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
    </insert>
</mapper>

 运行程序,查看数据库表:

使用Map集合可以传参,那使用pojo(简单普通的java对象)可以完成传参吗?测试一下: 

优化版2:

第一步:定义一个pojo类Car,提供相关属性。

package com.powernode.mybatis.pojo;

/**
 * POJOs,简单普通的Java对象。封装数据用的。
 * @author 老杜
 * @version 1.0
 * @since 1.0
 */
public class Car {
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", carNum='" + carNum + '\'' +
                ", brand='" + brand + '\'' +
                ", guidePrice=" + guidePrice +
                ", produceTime='" + produceTime + '\'' +
                ", carType='" + 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;
    }

    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;
    }
}

第二步:Java程序  CarMapperTest类中测试

 @Test
    public void testInsertCarByPOIO(){
        // 创建POJO,封装数据\
        Car car = new Car();
        car.setCarNum("100");
        car.setBrand("比亚迪汉");
        car.setGuidePrice(33.33);
        car.setProduceTime("2023-01-11");
        car.setCarType("燃油车");
        // 获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 执行SQL,传数据
        int count = sqlSession.insert("insertCarByPOJO", car);
        System.out.println("插入了几条记录" + count);
    }

第三步:SQL语句 CarMapper.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="car">
    <insert id="insertCarByPOJO">
        <!--#{} 里写的是POJO的属性名-->
        insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
    </insert>


</mapper>

第四步:运行程序,查看数据库表:

 

注意:其实传参数的时候有一个属性parameterType,这个属性用来指定传参的数据类型,不过这个属性是可以省略的 

二、delete(Delete)删

需求:根据car_num进行删除。

1、SQL语句这样写:CarMapper.xml文件

<delete id="deleteByCarNum">
  delete from t_car where car_num = #{SuiBianXie}
</delete>

2、CarMapperTest类中测试

 @Test
    public void testDeleteByCarNum(){
        // 获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 执行SQL语句
        int count = sqlSession.delete("deleteByCarNum", "133");
        System.out.println("删除了几条记录:" + count);
    }

3、运行并查看数据库

 

注意:当占位符只有一个的时候,${} 里面的内容可以随便写。 

三、update(Update)改

需求:修改id=9的Car信息,car_num为102,brand为比亚迪秦,guide_price为22.22,produce_time为2023-01-10,car_type为电车

修改前:

 1、SQL语句如下:CarMapper.xml文件

<update id="updateCarByPOJO">
  update t_car set 
    car_num = #{carNum}, brand = #{brand}, 
    guide_price = #{guidePrice}, produce_time = #{produceTime}, 
    car_type = #{carType} 
  where id = #{id}
</update>

2、CarMapperTest类中测试

@Test
    public void testUpdateCarByPOJO(){
        // 准备数据
        Car car = new Car();
        car.setId(9L);
        car.setCarNum("102");
        car.setBrand("比亚迪秦");
        car.setGuidePrice(22.22);
        car.setProduceTime("2023-01-10");
        car.setCarType("电车");
        // 获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtil.openSession();
        // 执行SQL语句
        int count = sqlSession.update("updateCarByPOJO", car);
        System.out.println("更新了几条记录:" + count);
    }

3、运行并查看数据库

 

同理增加一样,使用map传数据也是可以的。 

四、 select(Retrieve)查

select语句和其它语句不同的是:查询会有一个结果集。

1、查询一条数据

(1)SQL语句如下:CarMapper.xml文件

<select id="selectCarById">
  select * from t_car where id = #{id}
</select>

(2)CarMapperTest类中测试


@Test
public void testSelectCarById(){
    // 获取SqlSession对象
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 执行SQL语句
    Object car = sqlSession.selectOne("selectCarById", 1);
    System.out.println(car);
}

(3)运行:报了如下错误

大致的意思是:对于一个查询语句来说,你需要指定它的“结果类型”或者“结果映射”。

所以说,如果想让mybatis查询之后返回一个Java对象的话,至少要告诉mybatis返回一个什么类型的Java对象,可以在<select>标签中添加resultType属性,用来指定查询要转换的类型:

(4)修改后的SQL语句如下:CarMapper.xml文件

<select id="selectCarById" resultType="com.powernode.mybatis.pojo.Car">
  select * from t_car where id = #{id}
</select>

(5)再次运行

  • 运行后之前的异常不再出现了,这说明添加了resultType属性之后,解决了之前的异常,可以看出resultType是不能省略的。 
  • 但此时仍有问题,只有id和brand两个属性有值,其它属性的值都是null

查询结果集的列名:id, car_num, brand, guide_price, produce_time, car_type

Car类的属性名:id, carNum, brand, guidePrice, produceTime, carType

通过观察发现:只有id和brand是一致的,其他字段名和属性名对应不上,所以尝试在sql语句中使用as关键字来给查询结果列名起别名试试

(6)修改后的SQL语句如下:CarMapper.xml文件

<select id="selectCarById" 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 
  where 
    id = #{id}
</select>

(7)再次运行

 

2、查询多条数据

需求:查询所有的Car信息。

(1)SQL语句如下:CarMapper.xml文件

<!--虽然结果是List集合,但是resultType属性需要指定的是List集合中元素的类型。-->
<select id="selectCarAll" resultType="com.powernode.mybatis.pojo.Car">
  <!--记得使用as起别名,让查询结果的字段名和java类的属性名对应上。-->
  select
    id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
  from
    t_car
</select>

(2)CarMapperTest类中测试

@Test
public void testSelectCarAll(){
    // 获取SqlSession对象
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 执行SQL语句
    List<Object> cars = sqlSession.selectList("selectCarAll");
    // 输出结果
    cars.forEach(car -> System.out.println(car));
}

(三)运行

 五、关于SQL Mapper的namespace(命名空间)

在SQL Mapper配置文件中<mapper>标签的namespace属性可以翻译为命名空间,这个命名空间主要是为了防止sqlId冲突的。

(1)创建CarMapper2.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="car2">
    <select id="selectCarAll" 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>
</mapper>

不难看出,CarMapper.xml和CarMapper2.xml文件中都有 id="selectCarAll"

(2)将CarMapper2.xml配置到mybatis-config.xml文件中。

<mappers>
  <mapper resource="CarMapper.xml"/>
  <mapper resource="CarMapper2.xml"/>
</mappers>

(3)测试类中测试:CarMapperTest文件

@Test
public void testNamespace(){
    // 获取SqlSession对象
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 执行SQL语句
    List<Object> cars = sqlSession.selectList("selectCarAll");
    // 输出结果
    cars.forEach(car -> System.out.println(car));
}

(4)运行报如下错误:

 大致意思是:selectCarAll重名了,你要么在selectCarAll前添加一个名称空间,要有你改个其它名字

解决:ID重名了,此时用命名空间

(5)修改测试类中测试代码:CarMapperTest文件

@Test
public void testNamespace(){
    // 获取SqlSession对象
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 执行SQL语句
    List<Object> cars = sqlSession.selectList("car2.selectCarAll");
    // 输出结果
    cars.forEach(car -> System.out.println(car));
}

(6)再次运行

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

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

相关文章

redis的完整学习

Redis 1.Nosql 单机mysql缓存机制分库分表水平拆分mysql集群&#xff1a;本质上是数据库的读写 MyISAM:表锁&#xff0c;效率低Innodb&#xff1a;行锁 特点 解耦&#xff01; 1.方便扩展 2.大数据量高性能 3.数据类型是多样型的&#xff08;不需要设计数据库&#xff…

c语言 预处理

int main() {//printf("%s\n", __FILE__);//打印所在文件夹位置//printf("%d\n", __LINE__);//打印当前所在行号//printf("%s\n", __DATE__);//打印当前系统日期//printf("%s\n", __TIME__);//时间//printf("%s\n", __FUNCT…

分享155个ASP源码,总有一款适合您

ASP源码 分享155个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 154个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/12oYeESSXJCd32n463LBt4w?pwd5i1n 提取码&#x…

Java线程池中的execute和submit

一、概述 execute和submit都是线程池中执行任务的方法。 execute是Executor接口中的方法 public interface Executor {void execute(Runnable command); }submit是ExecuteService接口中的方法。 public interface ExecutorService extends Executor {<T> Future<T…

vue+element模仿腾讯视频电影网站(二),增加视频播放详情页

一.前言 1. 本项目在线预览&#xff1a;点击访问 2. 作者其他博客成品汇总预览&#xff1a;点击访问 3. 接上一篇&#xff1a;《vueelement模仿腾讯视频电影网站》 暂时源码并没有提供其他获取渠道&#xff0c;私聊作者获取即可&#xff0c;或通过博客后面名片添加作者&#…

【SSM】Mybatis小技巧汇总

Mybatis技巧一&#xff1a;#{} 和 ${} 的区别使用 ${} 特例一&#xff08;排序&#xff09;使用 ${} 特例二&#xff08;表连接&#xff09;使用 ${} 特例三&#xff08;批量删除&#xff09;技巧二&#xff1a;typeAliases 别名机制别名 Alias 性质技巧三&#xff1a;mappersm…

串级PID控制原理-1

串级计算机控制系统的典型结构如图1所示&#xff0c;系统中有两个PID控制器&#xff0c;Gc2(s)称为副调节器传递函数&#xff0c;包围Gc2(s)的内环称为副回路。Gc1(s)称为主调节器传递函数&#xff0c;包围Gc1(s)的外环称为主回路。主调节器的输出控制量u1作为副回路的给定量R2…

Vuex基本概念

一、基本概念vuex&#xff1a;为了解决不关联的组件整个网站状态数据共享问题&#xff0c;专为Vue.js开发的状态管理模式。采用集中式存储管理应用的所有组件状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。vuex有5个主要成员&#xff1a;state&#xff1…

DAMA数据管理知识体系指南之数据架构管理

第4章 4.1 简介 数据架构管理是定义和维护如下规范的过程&#xff1a; 提供标准的、通用的业务术语/辞典。 表达战略性的数据需求。 为满足如上需求&#xff0c;概述高层次的整合设计。 使企业战略和相关业务架构相一致。 数据架构是用于定义数据需求、指导对数据资产的整合和…

【C++】从0到1入门C++编程学习笔记 - 提高编程篇:STL常用容器(vector容器)

文章目录一、vector基本概念二、vector构造函数三、vector赋值操作四、vector容量和大小五、vector插入和删除六、vector数据存取七、vector互换容器八、vector预留空间一、vector基本概念 功能&#xff1a; vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector…

Discord多账号抢白名单,如何避免账号关联被封号?

相信玩NFT项目的都不会对Discord陌生&#xff0c;现在NFT的项目都会开Discord伺服器&#xff0c;并且将内容公告在上面、在伺服器里互动&#xff0c;所以如果你想参与NFT的世界&#xff0c;学会使用Discord是一件非常重要的事情。 东哥前2天也出了关于discord如何使用、如何抢白…

很多网站、APP 前段时间一下都变灰了。 先来感受一下变灰后的效果。

很多网站、APP 前段时间一下都变灰了。 先来感受一下变灰后的效果。 这种灰色的效果怎么实现的呢&#xff1f;如何做到图片、文字、按钮都变灰的效果呢&#xff1f; 方案 1&#xff0c;换一套灰色的 UI&#xff0c;那显然成本太大了&#xff0c;用脚指头想一想就知道不太可能…

C语言---选择排序和堆排序

文章目录前言一、简单选择排序1.简介2.算法思路3.代码实现二、堆排序1.简介2.算法思路3.代码实现总结前言 堆排序是选择排序的一种&#xff0c;今天我们讲解一下堆排序和简单选择排序 一、简单选择排序 1.简介 选择排序&#xff08;Selection sort&#xff09;是一种简单直观…

ZoomCharts JavaScript 1.20.2 Crack

深入探索数据 令人惊叹的数据可视化方式 - 这里是 ZoomCharts JavaScript 图表的不同交互可能性和功能。 内容向下钻取和向上钻取 深入研究特定数据点或获得更大的图景。通过放大或缩小与图表进行物理交互&#xff0c;浏览不同的数据级别。 数据过滤 选择一个或多个数据点查看具…

【软件测试面试】他凭什么能在面试中狂揽10个offer?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 小高&#xff1a; 记…

2023年屏蔽iOS16系统更新,去除小红点,最新方法

昨天开始&#xff0c;屏蔽iOS系统更新的旧文件已经过期&#xff0c;许多老粉收到了更新提醒&#xff0c;因此现在给大家带来最新的屏蔽文件 这个文件可以屏蔽iOS系统更新和提醒&#xff0c;防止手机自动下载更新。 这个方法支持所有 iPhone 和 iPad&#xff0c;支持所有 iOS 和…

# Android未来几年发展规划【纵横发展】

前言 如果你是移动开发人员&#xff0c;那么首先要跟上技术的最新发展趋势&#xff0c;并时刻关注新事物&#xff0c;即使有时你甚至需要质疑自己的信仰。应用开发人员一方面一直在努力想办法简化和缩短开发过程&#xff0c;另一方面也在努力构建最佳的设计和用户体验。每年我…

【MPP数据库】StarRocks分区、分桶探索与实践

1.先学习一下StarRocks的架构图&#xff1a; 2.基本概念 2.1 Row & Column 一张表包括行&#xff08;Row&#xff09;和列&#xff08;Column&#xff09;。Row 即用户的一行数据。Column 用于描述一行数据中不同的字段。 Column 可以分为两大类&#xff1a;Key 和 Value…

leetcode刷题记录总结-7.递归回溯算法(进行中)

文章目录零、回溯算法理论总览什么是回溯法回溯法的效率回溯法解决的问题如何理解回溯法回溯法模板一、组合问题[77. 组合](https://leetcode.cn/problems/combinations/)题解递归实现组合型枚举&#xff1a;每个点选与不选子集问题模板组合问题解决思路回溯思路&#xff1a;遍…

GAMES101笔记:辐射度量学(上)

Radiometry 辐射度量学 如何描述光照&#xff0c;定义了一系列的方法和单位准确度量光的空间属性&#xff1a; Radiant fluxintensityirradianceradiance 以物理正确的方式进行光照计算 Radiant Energy and Flux (Power) Radiant Energy 定义 Radiant Energy 是电磁辐射的能…