本章介绍的是接口中各种方法的参数
建表:t_student
表中现有数据:
简单类型包括:
- byte short int long float double char
- Byte Short Integer Long Float Double Character
- String
- java.util.Date
- java.sql.Date
需求:根据name查、根据id查、根据birth查、根据sex查
package com.powernode.mybatis.pojo;
import java.util.Date;
/**
* 学生类
* @author 老杜
* @version 1.0
* @since 1.0
*/
public class Student {
private Long id;
private String name;
private Integer age;
private Double height;
private Character sex;
private Date birth;
// constructor
// setter and getter
// toString
}
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Student;
import java.util.Date;
import java.util.List;
/**
* @author wuw
* @since 2023-04-10 13:46:17
*/
public interface StudentMapper {
/**
* 根据name查询
* @param name
* @return
*/
List selectByName(String name);
/**
* 根据id查询
* @param id
* @return
*/
Student selectById(Long id);
/**
* 根据birth查询
* @param birth
* @return
*/
List selectByBirth(Date birth);
/**
* 根据sex查询
* @param sex
* @return
*/
List selectBySex(Character sex);
}
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;
/**
* @author wuw
* @since 2023-04-04 09:42:28
*/
public class SqlSessionUtil {
private static SqlSessionFactory sqlSessionFactory;
/**
* 类加载时初始化sqlSessionFactory对象
*/
static {
try {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (Exception e) {
e.printStackTrace();
}
}
private static ThreadLocal local = new ThreadLocal<>();
/**
* 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。
*
* @return 新的会话对象
*/
public static SqlSession openSession() {
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
local.set(sqlSession);
}
return sqlSession;
}
/**
* 关闭SqlSession对象
* @param sqlSession
*/
public static void close(SqlSession sqlSession){
if (sqlSession != null) {
sqlSession.close();
}
local.remove();
}
}
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:1997/powernode
jdbc.username=root
jdbc.password=123456
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.StudentMapper;
import com.powernode.mybatis.pojo.Student;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class StudentMapperTest {
StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);
@Test
public void testSelectByName(){
List students = mapper.selectByName("张三");
students.forEach(student -> System.out.println(student));
}
@Test
public void testSelectById(){
Student student = mapper.selectById(2L);
System.out.println(student);
}
@Test
public void testSelectByBirth(){
try {
Date birth = new SimpleDateFormat("yyyy-MM-dd").parse("2022-08-16");
List students = mapper.selectByBirth(birth);
students.forEach(student -> System.out.println(student));
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Test
public void testSelectBySex(){
List students = mapper.selectBySex('男');
students.forEach(student -> System.out.println(student));
}
}
通过测试得知,简单类型对于mybatis来说都是可以自动类型识别的:
- 也就是说对于mybatis来说,它是可以自动推断出ps.setXxxx()方法的。ps.setString()还是ps.setInt()。它可以自动推断。
其实SQL映射文件中的配置比较完整的写法是:
其中sql语句中的javaType,jdbcType,以及select标签中的parameterType属性,都是用来帮助mybatis进行类型确定的。不过这些配置多数是可以省略的。因为mybatis它有强大的自动类型推断机制。
- javaType:可以省略
- jdbcType:可以省略
- parameterType:可以省略
如果参数只有一个的话,#{} 里面的内容就随便写了。对于 ${} 来说,注意加单引号。
需求:根据name和age查询
/**
* 根据name和age查询
* @param paramMap
* @return
*/
List selectByParamMap(Map paramMap);
@Test
public void testSelectByParamMap(){
// 准备Map
Map paramMap = new HashMap<>();
paramMap.put("nameKey", "张三");
paramMap.put("ageKey", 20);
List students = mapper.selectByParamMap(paramMap);
students.forEach(student -> System.out.println(student));
}
测试运行正常。
这种方式是手动封装Map集合,将每个条件以key和value的形式存放到集合中。然后在使用的时候通过#{map集合的key}来取值。
需求:插入一条Student数据
/**
* 保存学生数据
* @param student
* @return
*/
int insert(Student student);
insert into t_student values(null,#{name},#{age},#{height},#{birth},#{sex})
@Test
public void testInsert(){
Student student = new Student();
student.setName("李四");
student.setAge(30);
student.setHeight(1.70);
student.setSex('男');
student.setBirth(new Date());
int count = mapper.insert(student);
SqlSessionUtil.openSession().commit();
}
运行正常,数据库中成功添加一条数据。
这里需要注意的是:#{} 里面写的是属性名字。这个属性名其本质上是:set/get方法名去掉set/get之后的名字。
需求:通过name和sex查询
/**
* 根据name和sex查询
* @param name
* @param sex
* @return
*/
List selectByNameAndSex(String name, Character sex);
@Test
public void testSelectByNameAndSex(){
List students = mapper.selectByNameAndSex("张三", '女');
students.forEach(student -> System.out.println(student));
}
异常信息描述了:name参数找不到,可用的参数包括[arg1, arg0, param1, param2]
StudentMapper.xml文件:
通过测试可以看到:
- arg0 是第一个参数
- param1是第一个参数
- arg1 是第二个参数
- param2是第二个参数
实现原理:实际上在mybatis底层会创建一个map集合,以arg0/param1为key,以方法上的参数为value,例如以下代码:
Map map = new HashMap<>();
map.put("arg0", name);
map.put("arg1", sex);
map.put("param1", name);
map.put("param2", sex);
// 所以可以这样取值:#{arg0} #{arg1} #{param1} #{param2}
// 其本质就是#{map集合的key}
注意:使用mybatis3.4.2之前的版本时:要用#{0}和#{1}这种形式。
可以不用arg0 arg1 param1 param2吗?这个map集合的key我们自定义可以吗?当然可以。使用@Param注解即可。这样可以增强可读性。
需求:根据name和age查询
/**
* 根据name和age查询
* @param name
* @param age
* @return
*/
List selectByNameAndAge(@Param(value="name") String name, @Param("age") int age);
@Test
public void testSelectByNameAndAge(){
List stus = mapper.selectByNameAndAge("张三", 20);
stus.forEach(student -> System.out.println(student));
}
通过测试,一切正常。
核心:@Param("这里填写的其实就是map集合的key")