跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

时间:2021-08-21 00:52:22

使用MyBatis完成CRUD

配合视频教程观看,更易学习理解,课程讲解从Mybatis的一些核心要点与实战中的运用,一直过渡到MyBaits源码,由表及里的代入架构思维。一步一案例,一码一实操。从简单到深入,从实战到源码,MyBatis重点、难点、考点一网打尽。


●准备工作

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

○pom.xml

■打包方式jar

■依赖:

●mybatis依赖

●mysql驱动依赖

●junit依赖

●logback依赖

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

○CarMapper.xml放在类的根路径下

○logback.xml放在类的根路径下

○提供com.powernode.mybatis.utils.SqlSessionUtil工具类

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

1. insert(Create)

分析以下SQL映射文件中SQL语句存在的问题

<?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 >
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values('103', '奔驰E300L', 50.3, '2022-01-01', '燃油车')
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

存在的问题是:SQL语句中的值不应该写死,值应该是用户提供的。之前的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到架构思维(三)使用MyBatis完成CRUD- insert(Create)

在MyBatis中可以这样做:

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

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

Java程序这样写:

package com.powernode.mybatis;

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

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

/**
* 测试MyBatis的CRUD
* @author 老杜
* @version 1.0
* @since 1.0
*/
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);
}
}

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

SQL语句这样写:

<?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 >
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{k1},#{k2},#{k3},#{k4},#{k5})
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

#{} 的里面必须填写map集合的key,不能随便写。运行测试程序,查看数据库:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

如果#{}里写的是map集合中不存在的key会有什么问题?

<?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 >
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{kk},#{k2},#{k3},#{k4},#{k5})
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)运行程序:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)


 

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)


通过测试,看到程序并没有报错。正常执行。不过 #{kk} 的写法导致无法获取到map集合中的数据,最终导致数据库表car_num插入了NULL。

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

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", "燃油车");

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

SQL语句做如下修改,这样可以增强程序的可读性:

<?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 >
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

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

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)


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

●第一步:定义一个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;
}
}

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

●第二步:Java程序

@Test
public void testInsertCarByPOJO(){
// 创建POJO,封装数据
Car car = new Car();
car.setCarNum("103");
car.setBrand("奔驰C200");
car.setGuidePrice(33.23);
car.setProduceTime("2020-10-11");
car.setCarType("燃油车");
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL,传数据
int count = sqlSession.insert("insertCarByPOJO", car);
System.out.println("插入了几条记录" + count);
}

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

●第三步:SQL语句

<insert >
<!--#{} 里写的是POJO的属性名-->
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

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

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

#{} 里写的是POJO的属性名,如果写成其他的会有问题吗?

<insert >
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{a},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)运行程序,出现了以下异常:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)


错误信息中描述:在Car类中没有找到a属性的getter方法。

修改POJO类Car的代码,只将getCarNum()方法名修改为getA(),其他代码不变,如下:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

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

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)

经过测试得出结论:

如果采用map集合传参,#{} 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL。

如果采用POJO传参,#{} 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写(例如:getAge对应的是#{age},getUserName对应的是#{userName}),如果这样的get方法不存在会报错。

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

<insert  parameterType="java.util.Map">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

<insert parameterType="com.powernode.mybatis.pojo.Car">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD- insert(Create)