一、单个简单类型参数
🌔 1、简单类型参数都包括哪些?
- byte short int long float double char
- Byte Short Integer Long Float Double Character
- String
- java.util.Date
- java.sql.Date
🌔 2、准备工作 【创建操作的表和相关pojo类】
(1)设计表 t_car
(2)填写两条简单的数据
(3)在 idea 中创建一个新模块 mybatis-007-param 【文件结构如下】
(3)SqlSessionUtil 工具类 【其余Student类创建等就不展开赘述了,可以在前一个章节copy】
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(){
}
//定义一个SqlSession
private static final SqlSessionFactory sqlSessionFactory;
//在类加载的时候初始化SqlSessionFactory
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//定义一个全局的ThreadLocal,可以保证一个SqlSession对应一个线程
private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
//通过一个公有的方法为外部提供会话的对象 >> 确保同一个线程操作的是同一个连接对象
public static SqlSession openSession(){
//我们用local去获取会话
SqlSession sqlSession = local.get();
//如果当前没有开启的会话就去创建一个,如果get到了就用这个[确保我们操作的是同一个连接对象]
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
//将SqlSession对象绑定到当前线程上
local.set(sqlSession);
}
return sqlSession;
}
/**
* 关闭SqlSession对象并从当前线程中解绑
* @param sqlSession 会话对象
*/
public static void close(SqlSession sqlSession){
if(sqlSession != null){
sqlSession.close();
local.remove();
}
}
}
🌔3、对于传递的参数为单个简单类型时,我们列举了几个案例
- 根据 id、name、birth、sex 查询学生信息
- 接口如下:
public interface StudentMapper {
/**
* 接口中的参数为单个简单类型时
* 我们根据id、name、birth、sex查询
*/
List<Student> selectById(Long id);
List<Student> selectByName(String name);
List<Student> selectByBrith(Date brith);
List<Student> selectBySex(Character sex);
}
- Mapper映射文件如下:
<?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="com.powernode.mybatis.mapper.StudentMapper">
<select id="selectById" resultType="Student">
select * from t_student where id = #{
id}
</select>
<!--使用了类型内置别名-->
<select id="selectByName" resultType="Student" parameterType="string">
select * from t_student where name = #{
name}
</select>
<select id="selectByBrith" resultType="Student">
select * from t_student where birth = #{
birth}
</select>
<select id="selectBySex" resultType="Student">
select * from t_student where sex = #{
sex}
</select>
</mapper>
- 测试程序如下:
public class StudentMapperTest {
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
// 根据id查的数据只能有一条,所以不应该用List集合来接收查询结果
List<Student> students = mapper.selectById(1L);
students.stream().forEach(student -> System.out.println(student));
sqlSession.close();
}
@Test
public void testSelectByName(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.selectByName("张三");
students.stream().forEach(student -> System.out.println(student));
sqlSession.close();
}
@Test
public void testSelectByBirth() throws ParseException {
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date birth = sdf.parse("2022-11-01");
List<Student> students = mapper.selectByBrith(birth);
students.stream().forEach(student -> System.out.println(student));
sqlSession.close();
}
@Test
public void testSelectBySex() throws ParseException {
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.selectBySex('女');
students.stream().forEach(student -> System.out.println(student));
sqlSession.close();
}
}
- 测试结果 >> 成功
- 对于SQL语句可以指定 parameterType 的,如果不指定那么将有mybatis底层自动识别
- 而且mybatis还内置了一些基础类的别名:
二、Map参数
1、 Map参数是什么意思?;
- 就是我们要在数据库表接口中的操作方法传递的参数 >> 是一个 Map 集合
- 一般用于插入数据时候封装对象,集合的key就是传递参数占位符里面的内容
2、 通过一个案例来说明如何使用?【只给出接口中的方法、mapper中的SQL语句、测试片段其余部分与上述案例相同】;
(1)接口中的方法
/**
* 通过map参数保存学生信息,单个参数非简单类型
* @param map map对象
* @return 影响数据条数
*/
int insertStudentByMap(Map<String, Object> map);
(2)mapper 中的 SQL 语句
<insert id="insertStudentByMap">
<!--占位符中传递的是map的key-->
insert into t_student (id, name, age, sex, birth, height)
values (null, #{
name}, #{
age}, #{
sex}, #{
birth}, #{
height})
</insert>
(3)测试片段
@Test
public void testInsertStudentByMap(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Map<String, Object> map = new HashMap<>();
// 一个map对象代表一个学生信息, map 的key对应表中字段--value对应属性值
map.put("name", "李元霸");
map.put("age", 20);
map.put("height", 1.81);
map.put("sex", '男');
map.put("birth", new Date());
int count = mapper.insertStudentByMap(map);
sqlSession.commit();
sqlSession.close();
}
(4)运行结果如下:
三、实体类参数
1、 这是我们比较常用的方式,用一个普通java类来封装我们的数据库表中的字段;
2、 我们现在要通过实体类参数插入一条数据;
(1)创建Student类
package com.powernode.mybatis.pojo;
import java.util.Date;
/**
* @author Bonbons
* @version 1.0
*/
public class Student {
private Long id;
private String name;
private Integer age;
private Double height;
private Date birth;
private Character sex;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", height=" + height +
", brith=" + birth +
", sex=" + sex +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date brith) {
this.birth = birth;
}
public Character getSex() {
return sex;
}
public void setSex(Character sex) {
this.sex = sex;
}
public Student() {
}
public Student(Long id, String name, Integer age, Double height, Date brith, Character sex) {
this.id = id;
this.name = name;
this.age = age;
this.height = height;
this.birth = brith;
this.sex = sex;
}
}
(2)接口中的方法
/**
* 通过POJO类对象传递参数信息
* @param student 学生类的对象
* @return 影响数据条数
*/
int insertStudentByPOJO(Student student);
(3)映射文件中的 SQL 语句
- 此处占位符内的字段是获取对应属性值的 get方法去掉get和将首字母转化为小写后的参数
<insert id="insertStudentByPOJO" parameterType="student">
insert into t_student (id, name, age, sex, birth, height)
values (null, #{
name}, #{
age}, #{
sex}, #{
birth}, #{
height})
</insert>
(4)相应的测试片段
@Test
public void testInsertStudentByPOJO(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student(null, "李白", 30, 1.82, new Date(), '女');
int count = mapper.insertStudentByPOJO(student);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
(5)测试结果如下
四、多参数
🌔 1、以上的案例都是参数只有一个时,那么如果我们的方法需要传递多个参数应该如何处理呢?
- mybatis 为我们提供了两种默认的参数传递机制
- 假如传递的为两个参数,此处以根据姓名和性别查询学生数据
- 那么在接口中的方法应该是这样的:
/**
* 根据名字和性别查询学生信息
* @param name 名字
* @param sex 性别
* @return 返回查询结果
*/
List<Student> selectByNameAndSex(String name, Character sex);
- 重点来了,在Mapper的映射文件的SQL语句中,我们应该怎么写呢?【占位符中应该填什么参数】
<select id="selectByNameAndSex" resultType="student">
select * from t_student where name = #{
} and sex = #{
}
</select>
🌔2、mybatis为我们提供了两种默认的参数?
- 第一种:使用参数 argN 【N对应我们第 i - 1 个参数】
- 第二种:使用参数paramN 【N对应我们的第i个参数】
所以上面的SQL语句可以写成一下两种形式:【此处是为了方便看将两条ID相同的SQL语句写到一块去了】
<select id="selectByNameAndSex" resultType="student">
select * from t_student where name = #{
arg0} and sex = #{
arg1}
</select>
<select id="selectByNameAndSex" resultType="student">
select * from t_student where name = #{
param1} and sex = #{
param2}
</select>
- 在测试文件中,我们正常调用即可
public void testSelectByNameAndSex(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.selectByNameAndSex("李白", '女');
students.stream().forEach(student -> System.out.println(student));
sqlSession.commit();
sqlSession.close();
}
🌔3、我们还可以采用 @Param 注解的方式指定使用什么参数名
- 在我们制定接口方法的时候,我们可以通过 @Param 注解指明使用什么参数名 【可以参考下面的方法】
/**
* 通过注解来为多个参数指明参数名,底层实现不再使用默认的arg、param了
* map.put("name", name)
* @param name
* @param sex
* @return
*/
List<Student> selectByNameAndSex2(@Param("name") String name, @Param("sex") Character sex);
- 就是在参数类型前面添加 @Param(参数名)
- 在我们写SQL语句的时候就可以使用我们制定的参数名了
<select id="selectByNameAndSex2" resultType="student">
select * from t_student where name = #{
name} and sex = #{
sex}
</select>
- 此时仍然可以使用 param1、param2 … 作为参数名传递参数,但是不能使用 arg0、arg1、… 的方式了
- 测试方法中的代码块不变:
public void testSelectByNameAndSex2(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.selectByNameAndSex2("李白", '女');
students.stream().forEach(student -> System.out.println(student));
sqlSession.commit();
sqlSession.close();
}
🌔4、可以根据一下内容简单了解一下Param注解的原理: