Mybatis查询
MyBatis支持多种类型的查询,以下是一些常见的MyBatis查询方式:
- 基本查询(Basic Query) :
使用SQL语句进行基本的数据库查询,通过select、insert、update和delete等操作来执行CRUD操作。 - 注解查询(Annotation Query) :
使用注解(例如@Select、@Insert、@Update、@Delete等)在Mapper接口中直接编写SQL语句来执行查询。 - XML配置文件查询(XML Configuration Query) :
使用XML配置文件来编写SQL语句,然后在Mapper接口中引用这些SQL语句进行查询。 - 动态SQL查询(Dynamic SQL Query) :
MyBatis提供了动态SQL的功能,可以根据条件来动态地生成SQL语句,实现灵活的查询。 - 参数传递查询(Parameter Passing Query) :
通过参数传递方式将数据传递给SQL语句,例如使用@Param注解传递参数,或者使用#{}占位符进行参数绑定。 - 结果映射查询(Result Mapping Query) :
将查询结果映射为Java对象,可以使用<resultMap>标签或@Results注解来进行结果映射。 - 关联查询(Association Query) :
在查询中使用嵌套查询或者联合查询来关联多个表,将结果映射为复杂的Java对象结构。 - 分页查询(Pagination Query) :
MyBatis支持对查询结果进行分页处理,可以使用RowBounds或者插件等方式实现分页查询。 - 缓存查询(Caching Query) :
MyBatis支持查询结果的缓存,可以减少对数据库的访问,提高性能。 - 存储过程调用(Stored Procedure) :
MyBatis支持调用数据库中的存储过程,可以在Mapper接口中执行存储过程。
查询比较官方的写法
环境准备
-- 员工管理
create table emp (
id int unsigned primary key auto_increment comment 'ID',
username varchar(20) not null unique comment '用户名',
password varchar(32) default '123456' comment '密码',
name varchar(10) not null comment '姓名',
gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
image varchar(300) comment '图像',
job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
entrydate date comment '入职时间',
dept_id int unsigned comment '部门ID',
create_time datetime not null comment '创建时间',
update_time datetime not null comment '修改时间'
) comment '员工表';
INSERT INTO emp
(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES
(1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,now(),now()),
(2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,now(),now()),
(3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,now(),now()),
(4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,now(),now()),
(5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,now(),now()),
(6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,now(),now()),
(7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,now(),now()),
(8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,now(),now()),
(9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,now(),now()),
(10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,now(),now()),
(11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,now(),now()),
(12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,now(),now()),
(13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,now(),now()),
(14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,now(),now()),
(15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,now(),now()),
(16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2010-01-01',2,now(),now()),
(17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-21',NULL,now(),now());
查询所有方法
//查询
@Select("select * from emp")
List<Emp> findAll();
测试
//查询所有
@Test
public void testFindAll() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.findAll();
empList.forEach(e -> System.out.println(e));//lambda方式打印
MybatisUtil.close(sqlSession);
}
驼峰映射
当表中字段和类中属性的关系是_和驼峰写法时,可以开启mybatis的自动驼峰映射
<setting name="mapUnderscoreToCamelCase" value="true"/>
起别名
当表中字段和类中属性完全没有关系时,可以使用别名来修改sql返回集中字段的名称
给不对应的字段起别名
//查询
@Select("select id, username, password, name, gender, image, job, entrydate as ed, dept_id, create_time, update_time from emp")
List<Emp> findAll2();
测试
//查询所有
@Test
public void testFindAll2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.findAll2();
empList.forEach(e -> System.out.println(e));//lambda方式打印
MybatisUtil.close(sqlSession);
}
自定义映射
当表中字段和类中属性完全没有关系时,可以通过@Results进行手动结果映射
自定义结果映射
//查询
@Results({//@Results: 自定义结果映射
@Result(column = "entrydate", property = "ed"),//@Result一条映射规则 (column = "数据表中字段名", property = "实体类属性名")
@Result(column = "dept_id", property = "deptId")
})
@Select("select * from emp")
List<Emp> findAll3();
测试
//查询所有
@Test
public void testFindAll3() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.findAll3();
empList.forEach(e -> System.out.println(e));//lambda方式打印
MybatisUtil.close(sqlSession);
}
条件查询
当查询方法出现多个查询条件时,需要使用@Param注解设置对应关系
添加条件查询的方法
//#{} 里面的内容
//1. 如果参数是一个对象类型, #{}写的是对象中的属性名
//2. 如果参数是一个简单类型(8基本 + 8包装 +String) ,#{}可以随便写, 但是推荐写方法形参名
//3. 如果参数是多个简单类型的参数, #{}中写的是@Param注解中的值
//条件查询
@Select("select * from emp where name = #{name} and gender = #{gender} and entrydate between #{begin} and #{end}")
List<Emp> findList(@Param("name") String name, @Param("gender") Short gender, @Param("begin") LocalDate begin, @Param("end") LocalDate end);
测试
//条件查询
@Test
public void testFindList() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.findList("张三丰", (short) 1, LocalDate.of(2002, 01, 01), LocalDate.of(2023, 12, 31));
empList.forEach(e -> System.out.println(e));//lambda方式打印
MybatisUtil.close(sqlSession);
}
模糊查询
当查询sql中出现模糊查询语法时,需要使用concat函数连接条件,比如根据用户名进行模糊查询
`where name like '%张%'----------------->where name like concat('%',#{username},'%')
添加条件查询的方法
//模糊查询
@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin} and #{end}")
List<Emp> findListLike(@Param("name") String name, @Param("gender") Short gender, @Param("begin") LocalDate begin, @Param("end") LocalDate end);
测试
//模糊查询
@Test
public void testFindListLike() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.findListLike("张", (short) 1, LocalDate.of(2002, 01, 01), LocalDate.of(2023, 12, 31));
empList.forEach(e -> System.out.println(e));//lambda方式打印
MybatisUtil.close(sqlSession);
}
所有写一起
Emp类
package com.itheima.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private String image;
private Short job;
//注意:这四个属性跟数据表中的字段不一致
private LocalDate ed;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Mapper类
package com.itheima.mapper;
import com.itheima.domain.Emp;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface EmpMapper {
@Select("select * from emp")
List<Emp> findAll();
//起别名
@Select("select id,username,password,name,gender,image,job," +
"entrydate as ed,dept_id,create_time,update_time from emp")
List<Emp> findAll2();
//起别名二
@Select("select *,entrydate as ed from emp")
List<Emp> findAll3();
//建立映射
@Results({
@Result(column = "entrydate",property = "ed"),
@Result(column = "update_time",property = "updateTime")
})
@Select("select * from emp")
List<Emp> findAll4();
//添加条件查询的方法
//#{} 里面的内容
//1. 如果参数是一个对象类型, #{}写的是对象中的属性名
//2. 如果参数是一个简单类型(8基本 + 8包装 +String) ,#{}可以随便写, 但是推荐写方法形参名
//3. 如果参数是多个简单类型的参数, #{}中写的是@Param注解中的值
@Select("select * from emp where name = #{name} and gender = #{gender} and " +
"entrydate between #{begin} and #{end}")
List<Emp> findList(@Param("name") String name, @Param("gender") Short gender,
@Param("begin") LocalDate begin, @Param("end") LocalDate end);
//模糊查询
@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} " +
" and entrydate between #{begin} and #{end}")
List<Emp> findListLike(@Param("name") String name, @Param("gender") Short gender,
@Param("begin") LocalDate begin, @Param("end") LocalDate end);
//注意: 对于同一个方法,使用xml写sql的话,就不能在使用注解写sql了
//@Select("select * from emp where id = #{id}")
Emp findById(@Param("id") Integer id);
List<Emp> findByCondition(@Param("name") String name,
@Param("gender") Short gender,
@Param("begin") LocalDate begin,
@Param("end") LocalDate end);
//根据ID更新不为空的字段 修改
void update(Emp emp);
//删除
void deleteByIds(@Param("ids") List<Integer> ids);
//案例的 myBatis forEach 插入
void insertEmp(@Param("empList") List<Emp> empList);
}
Util类
package com.itheima.util;
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.InputStream;
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory = null;
//保证SqlSessionFactory仅仅创建一次
static {
try {
//读取配置文件
InputStream stream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取sqlSession
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
//提交事务 关闭sqlSession
public static void close(SqlSession sqlSession) {
if (sqlSession != null) {
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
}
}
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="com.itheima.mapper.EmpMapper">
<sql id="selectUser">
select id,
username,
password,
name,
gender,
image,
job,
entrydate as ed,
dept_id,
create_time,
update_time
from emp
</sql>
<!-- id : 哪个方法-->
<!-- resultType:方法返回值类型-->
<select id="findById" resultType="com.itheima.domain.Emp">
<include refid="selectUser"></include>
where id = #{id}
</select>
<!--
字符串需要跟null和空串比较
其他类型只要跟null比较
if:使用test进行条件判断,只有条件成立,条件中的sql才会生效
where:只会在<where>标签内部有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR。
-->
<select id="findByCondition" resultType="com.itheima.domain.Emp">
select * from emp
<where>
<if test="name!=null and name!=''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin !=null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
</select>
<!---->
<update id="update">
update emp
<set>
<if test="username !=null and username !=''">
username = #{username},
</if>
<if test="password !=null and password !=''">
password = #{password},
</if>
<if test="name !=null and name !=''">
name = #{name},
</if>
<if test="gender !=null">
gender = #{gender},
</if>
<if test="image !=null and image !=''">
image = #{image},
</if>
<if test="job !=null">
job= #{job},
</if>
<if test="ed !=null">
entrydate = #{ed},
</if>
<if test="createTime !=null">
create_Time = #{createTime},
</if>
<if test="updateTime !=null">
update_time = #{update },
</if>
</set>
where id = #{id}
</update>
<!--
* collection:集合名称
* item:集合遍历出来的元素
* separator:每一次遍历使用的分隔符
* open: 遍历开始前拼接的片段
* close:遍历结束后拼接的片段
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<!--
* 案例的 myBatis forEach 插入
-->
<insert id="insertEmp">
insert into emp(id,username,password,name,
gender,create_time,update_time)
values
<foreach collection="empList" item="emp" separator=",">
(null ,#{emp.username},#{emp.password},#{emp.name},
#{emp.gender},now(),now())
</foreach>
</insert>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
* 定义SQL片段: <sql id="selectUser"></sql>
* 引用SQL片段: <include refid="selectUser"></include>
-->
<settings>
<!-- 驼峰映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--在控制台输出发送的sql日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--目前只关注这部分内容,它的作用就是声明要连接的数据信息-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--声明含有sql的接口所在包-->
<package name="com.itheima.mapper"/>
</mappers>
</configuration>
测试类
package com.itheima.test;
import com.itheima.domain.Emp;
import com.itheima.mapper.EmpMapper;
import com.itheima.util.MybatisUtil;
import jdk.swing.interop.SwingInterOpUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class EmpMapperTest {
@Test
public void testFindall(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> all = mapper.findAll();
all.forEach(new Consumer<Emp>() {
@Override
public void accept(Emp emp) {
System.out.println(emp);
}
});
MybatisUtil.close(sqlSession);
}
@Test
public void testFindall1(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//方法二
List<Emp> all = mapper.findAll2();
//lambda写法
all.forEach(emp -> System.out.println(emp));
MybatisUtil.close(sqlSession);
}
@Test
public void testFindall2(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//方法三 起别名
List<Emp> all = mapper.findAll3();
//静态方法写法
all.forEach(System.out::println);
MybatisUtil.close(sqlSession);
}
@Test
public void testFindall3(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//方法四 映射
List<Emp> all = mapper.findAll4();
//静态方法写法
all.forEach(System.out::println);
MybatisUtil.close(sqlSession);
}
//添加条件查询的方法
@Test
public void testFindList(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> emps = mapper.findList("张三丰", (short) 1, LocalDate.of(2002, 1, 1),
LocalDate.of(2023, 12, 31));
emps.forEach(new Consumer<Emp>() {
@Override
public void accept(Emp emp) {
System.out.println(emp);
}
});
MybatisUtil.close(sqlSession);
}
//模糊查询
@Test
public void testFindListLike(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> emps = mapper.findListLike("张", (short) 1, LocalDate.of(2002, 01, 01),
LocalDate.of(2023,12,31));
emps.forEach(emp -> System.out.println(emp));
MybatisUtil.close(sqlSession);
}
//根据id查询
@Test
public void testFindById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = empMapper.findById(1);
System.out.println(emp);
MybatisUtil.close(sqlSession);
}
//条件查询
@Test
public void testFindByCondition(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//查姓张的
List<Emp> empList = mapper.findByCondition("张", (short) 1, null, null);
empList.forEach(e -> System.out.println(e));
MybatisUtil.close(sqlSession);
}
//更新测试
@Test
public void testUpdate(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setId(1);
emp.setUsername("程序员");
emp.setName("陈某人");
mapper.update(emp);
MybatisUtil.close(sqlSession);
}
//根据ID批量删除
@Test
public void deleteByIds(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
mapper.deleteByIds(Arrays.asList(10,11,12));
MybatisUtil.close(sqlSession);
}
/**
* 案例的 myBatis forEach 插入
*/
@Test
public void insertEmp(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
ArrayList<Emp> empList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
Emp emp = new Emp();
emp.setUsername("啦啦啦啦"+i);
emp.setPassword("123456");
emp.setName("李思"+i);
emp.setGender((short) 2);
empList.add(emp);
}
mapper.insertEmp(empList);
MybatisUtil.close(sqlSession);
}
}