使用 MyBatis 完成 CRUD
CRUD:
- C:Create
- R:Retrieve
- U:Update
- D:Delete
# 1. Create
# 1.1 使用 map 传参
为了实现向 SQL 中传入参数,在 MyBatis 中可以这么做:
- 在 Java 程序中,将数据放到 Map 中
- 在 SQL 语句中使用
#{map 中的 key}
来完成传值,#{}
是一个占位符
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("carNum", "103");
map.put("brand", "奔驰E300L");
map.put("guidePrice", 50.3);
map.put("produceTime", "2020-10-01");
map.put("carType", "燃油车");
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句(使用map集合给sql语句传递数据)
int count = sqlSession.insert("insertCar", map);
System.out.println("插入了几条记录:" + count);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 id="insertCar">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>
</mapper>
2
3
4
5
6
7
8
9
10
11
#{}
里面必须填写 map 的 key,不能随便写。
# 1.2 使用 POJO 传参
首先定义一个 POJO 类 Car:
@Data
public class Car {
private Long id;
private String carNum;
private String brand;
private Double guidePrice;
private String produceTime;
private String carType;
}
2
3
4
5
6
7
8
9
数据类型建议使用包装类,这样可以防止 null 的问题。
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);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SQL 语句:
<insert id="insertCarByPOJO">
<!--#{} 里写的是POJO的属性名-->
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>
2
3
4
可以看到,#{}
里面填的 POJO 的属性名。
# 1.3 总结
- 如果采用 map 传参,
#{}
里面写的是 map 的 key。如果 key 不存在则填充 NULL。 - 如果采用 POJO 传参,
#{}
里面写的是 POJO 类的getXxx()
方法的 xxx 名,如果不匹配则报错。
在 XML 中写 SQL 时,标签上还有一个属性 parameterType
,这个属性用来指定传参的数据类型,不过这个属性是可以省略的:
<insert id="insertCar" 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 id="insertCarByPOJO" 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>
2
3
4
5
6
7
# 2. Delete
假设我们要根据 car_num 来进行 delete。
在 MyBatis 中,如果只有一个参数值,那么 #{}
中的内容可以随便写:
<delete id="deleteByCarNum">
delete from t_car where car_num = #{SuiBianXie}
</delete>
2
3
Java 程序:
@Test
public void testDeleteByCarNum(){
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句
int count = sqlSession.delete("deleteByCarNum", "102");
System.out.println("删除了几条记录:" + count);
}
2
3
4
5
6
7
8
# 3. Update
SQL 语句:
<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
3
4
5
6
7
Java 代码:
@Test
public void testUpdateCarByPOJO(){
// 准备数据
Car car = new Car();
car.setId(34L);
car.setCarNum("102");
car.setBrand("比亚迪汉");
car.setGuidePrice(30.23);
car.setProduceTime("2018-09-10");
car.setCarType("电车");
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句
int count = sqlSession.update("updateCarByPOJO", car);
System.out.println("更新了几条记录:" + count);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
当然,也可以使用 map 来传值。
# 4. Retrieve
SELECT 语句与其他语句不同的是:查询会有一个结果集。来看一下 MyBatis 是如何处理结果集的。
在 MyBatis 中,对于一个查询语句来说,你需要指定它的 resultType 或者 resultMap。
# 4.1 查询一条数据
如果想让 MyBatis 查询之后返回一个 Java 对象的话,需要告诉 MyBatis 返回一个什么类型的 Java 对象,可以在 <select>
标签中添加 resultType 属性,用来指定查询要转换的类型。
需求:查询 id 为 1 的 car 信息
SQL 语句如下:
<select id="selectCarById" resultType="com.powernode.mybatis.pojo.Car">
select * from t_car where id = #{id}
</select>
2
3
Java 程序:
@Test
public void testSelectCarById(){
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句
Object car = sqlSession.selectOne("selectCarById", 1);
System.out.println(car);
}
2
3
4
5
6
7
8
但很不幸的是,数据库表中的字段是 produce_time
这样的风格,而 Java 对象的字段却是 produceTime
这样的风格,这导致无法完成字段的映射。目前我们可以在 SELECT 语句中使用 AS 关键字来给列名起一个别名来解决。当然还有其他解决方案,我们后面再看。
<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>
2
3
4
5
6
7
8
# 4.2 查询多条数据
当结果集是个 List 集合时,<select>
标签的 resultType 属性只需要指定 List 集合中元素的类型即可。
需求:查询所有 car 的信息。
SQL 语句如下:
<!--虽然结果是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
3
4
5
6
7
8
Java 代码如下:
@Test
public void testSelectCarAll(){
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句
List<Object> cars = sqlSession.selectList("selectCarAll");
// 输出结果
cars.forEach(car -> System.out.println(car));
}
2
3
4
5
6
7
8
9
# 5. 关于 SQL Mapper 的 Namespace
在 SQL mapper 配置文件中 <mapper>
标签的 namespace 属性主要是为了防止 SQL Id 冲突的。
比如我们创建一个 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>
2
3
4
5
6
7
8
9
10
11
12
13
此时,CarMapper.xml 和 CarMapper2.xml 文件中都有 id="selectCarAll"
。
再将 CarMapper2.xml 配置到 mybatis-config.xml 文件中:
<mappers>
<mapper resource="CarMapper.xml"/>
<mapper resource="CarMapper2.xml"/>
</mappers>
2
3
4
此时,如果想使用 Namespace car2
中的 selectCarAll
SQL,那么我们的 Java 需要显式指定 namespace:
@Test
public void testNamespace(){
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句
//List<Object> cars = sqlSession.selectList("car.selectCarAll");
List<Object> cars = sqlSession.selectList("car2.selectCarAll");
// 输出结果
cars.forEach(car -> System.out.println(car));
}
2
3
4
5
6
7
8
9
10