MyBatis(三)使用MyBatis完成CRUD(增删改查)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
准备工作
1、创建moduleMaven的普通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
一、insertCreate增
分析以下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这个属性用来指定传参的数据类型不过这个属性是可以省略的
二、deleteDelete删
需求根据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、运行并查看数据库
注意当占位符只有一个的时候${} 里面的内容可以随便写。
三、updateUpdate改
需求修改id=9的Car信息car_num为102brand为比亚迪秦guide_price为22.22produce_time为2023-01-10car_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传数据也是可以的。
四、 selectRetrieve查
select语句和其它语句不同的是查询会有一个结果集。
1、查询一条数据
1SQL语句如下CarMapper.xml文件
<select id="selectCarById">
select * from t_car where id = #{id}
</select>
2CarMapperTest类中测试
@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信息。
1SQL语句如下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>
2CarMapperTest类中测试
@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再次运行