Mybatis简介
Data Access Objects(DAO)
定制化 SQL
、存储过程以及高级映射
的优秀的持久层框架使用简单的XML或注解用于配置和原始映射
,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录MyBatis官方中文文档
JDBC
SQL语句 夹杂在Java代码中耦合度高
,导致硬编码内伤Hibernate 和 JPA
MyBatis
轻量级,性能出色 ,半自动的ORM框架
SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
开发效率稍逊于HIbernate,但是完全能够接受
在idea新建MyBatisDemo项目,再新建module名为MyBatis_Demo1,项目目录如图:
MySQL数据库脚本如下:
drop database if exists mybatis_demo;
create database mybatis_demo;
use mybatis_demo;
create table t_user(
`id` int primary key auto_increment,
`username` varchar(20),
`password` varchar(20),
`gender` char,
`age` int,
`email` varchar(25)
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
create table t_department(
`did` int primary key,
`dname` varchar(20)
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
create table t_emp(
`id` int primary key auto_increment,
`emp_name` varchar(20),
`password` varchar(20),
`gender` char,
`age` int,
`email` varchar(25),
`did` int,
constraint fk_employee_department foreign key(`did`) references t_department(`did`)
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
insert t_user values(null,'张三','123456','男',22,'[email protected]');
insert into t_department values(1,"开发部");
insert into t_department values(2,"测试部");
insert into t_department values(3,"运维部");
insert into t_emp values (null, "张三", "aaa", "男", 22, "[email protected]", 1);
insert into t_emp values (null, "李四", "bbb", "女", 22, "[email protected]", 2);
insert into t_emp values (null, "王五", "ccc", "男", 22, "[email protected]", 3);
insert into t_emp values (null, "赵六", "ddd", "女", 22, "[email protected]", 1);
insert into t_emp values (null, "田七", "eee", "男", 22, "[email protected]", 2);
在MyBatis—Demo1下的pom.xml文件添加依赖
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.atguigugroupId>
<artifactId>MyBatisDemoartifactId>
<version>1.0-SNAPSHOTversion>
parent>
<artifactId>MyBatis_Demo1artifactId>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.7version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.2.5version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.17version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.4version>
<scope>providedscope>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
project>
在pom.xml加入依赖
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
加入log4j的配置文件
DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
layout>
appender>
<logger name="java.sql">
<level value="debug" />
logger>
<logger name="org.apache.ibatis">
<level value="info" />
logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
root>
log4j:configuration>
在src/main/resources目录下新建 datasorce.properties 配置文件
# jdbc数据源
jdbc.username = root
jdbc.password = 360421
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis_demo?useUnicode = true&characterEncoding = UTF-8&serverTimezone = UTC
# druid数据源
# 驱动名称
druid.driverClassName = com.mysql.cj.jdbc.Driver
# 连接数据库的URL
druid.url = jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
# mysql的用户与密码
druid.username = root
druid.password = 360421
# 初始化时的物理连接的个数
druid.initialSize = 5
# 最大连接池数量
druid.maxActive = 10
# 获取连接时最大等待时间
druid.maxWait = 3000
习惯上命名为
mybatis-config.xml
,这个文件名仅仅只是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。
核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息
核心配置文件存放的位置是src/main/resources目录下
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="datasource.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="com.atguigu.util.DruidDataSourceFactory">
<property name="driverClassName" value="${druid.driverClassName}"/>
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
<property name="initialSize" value="${druid.initialSize}"/>
<property name="maxActive" value="${druid.maxActive}"/>
<property name="maxWait" value="${druid.maxWait}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
mappers>
configuration>
在pojo包下创建User实体类:
package com.atguigu.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @author : Sakura
* @className : User
* @description : User实体类
* @createTime : 2023-08-08 16:12:18
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String email;
private String gender;
}
在util包下创建DruidDataSourceFactory类,用于配置Druid数据源:
package com.atguigu.util;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
public class DruidDataSourceFactory extends PooledDataSourceFactory {
public DruidDataSourceFactory(){
this.dataSource = new DruidDataSource();
}
}
在mapper包下创建UserMapper类
MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类
package com.atguigu.mapper;
import com.atguigu.pojo.User;
import java.util.List;
/**
* @author : Sakura
* @className : UserMapper
* @description : TODO
* @createTime : 2023-08-08 16:18:35
*/
public interface UserMapper {
/**
* 添加用户信息
* @return
*/
int insertUser(User user);
/**
* 根据id查找用户
* @param id
* @return
*/
User getUserById(Integer id);
/**
* 获取User列表
* @return
*/
List<User> getUserList();
/**
* 修改用户信息
* @param user
* @return
*/
int updateUser(User user);
/**
* 根据id删除用户
* @param id
* @return
*/
int deleteUserById(Integer id);
}
Java概念 | 数据库概念 |
---|---|
类 | 表 |
属性 | 字段/列 |
对象 | 记录/行 |
src/main/resources/mappers
目录下mapper接口的全类名和映射文件的命名空间(namespace)保持一致
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.UserMapper">
<insert id="insertUser">
insert into t_user
values (#{id}, #{username}, #{password}, #{gender}, #{age}, #{email})
insert>
<select id="getUserById" resultType="com.atguigu.pojo.User">
select * from t_user
where id = #{id}
select>
<resultMap id="userResultMap" type="com.atguigu.pojo.User">
<result column="id" property="id" />
<result column="username" property="username" />
<result column="password" property="password" />
<result column="gender" property="gender" />
<result column="age" property="age" />
<result column="email" property="email" />
resultMap>
<select id="getUserList" resultMap="userResultMap">
select * from t_user
select>
<update id="updateUser">
update t_user
set username = #{username}, password = #{password}, gender = #{gender}, age = #{age}, email = #{email}
where id = #{id}
update>
<delete id="deleteUserById" >
delete from t_user
where id = #{id}
delete>
mapper>
import com.atguigu.mapper.UserMapper;
import com.atguigu.pojo.User;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author : Sakura
* @className : UserMapperTest
* @description : TODO
* @createTime : 2023-08-08 16:23:30
*/
public class UserMapperTest {
/**
* 此时需要手动提交事务,如果要自动提交事务,则在获取sqlSession对象时,使用`SqlSession sqlSession = sqlSessionFactory.openSession(true);`,传入一个Boolean类型的参数,值为true,这样就可以自动提交
* @throws IOException
*/
@Test
public void testInsertUser() throws IOException {
User user = new User(null,"李四","1234",16,"[email protected]","女");
// 读取MyBatis的核心配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 获取SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 获取sqlSession,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
// 通过openSession(true)方法创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句
int i = userMapper.insertUser(user);
// 提交事务
// sqlSession.commit();
System.out.println("i = " + i);
}
/**
* 获取UserMapper实例
* @return
*/
public UserMapper getUserMapper() throws IOException {
// 创建SqlSessionFactory实例
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 创建SqlSession实例,并设置自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 通过代理模式创建UserMapper接口的代理实现类对象
return sqlSession.getMapper(UserMapper.class);
}
/**
* 根据id查找用户
* @throws IOException
*/
@Test
public void testGetUserById() throws IOException {
UserMapper userMapper = getUserMapper();
User user = userMapper.getUserById(1);
System.out.println(user);
}
/**
* 修改用户信息
* @throws IOException
*/
@Test
public void testUpdateUser() throws IOException {
UserMapper userMapper = getUserMapper();
User user = userMapper.getUserById(1);
System.out.println(user);
user.setUsername("Sakura");
System.out.println(user);
}
/**
* 获取User列表
* @throws IOException
*/
@Test
public void testGetUserList() throws IOException {
UserMapper userMapper = getUserMapper();
List<User> userList = userMapper.getUserList();
System.out.println(userList);
}
/**
* 根据id删除用户
* @throws IOException
*/
@Test
public void testDeleteUserById() throws IOException {
UserMapper userMapper = getUserMapper();
int i = userMapper.deleteUserById(4);
System.out.println(i);
}
}
SqlSession sqlSession = sqlSessionFactory.openSession(true);
,传入一个Boolean类型的参数,值为true,这样就可以自动提交点击查看官方中文文档
核心配置文件中的标签必须按照
固定的顺序(
有的标签可以不写,但顺序一定不能乱):
properties
、settings
、typeAliases
、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments
、databaseIdProvider、mappers
DOCTYPE configuration
PUBLIC "-//MyBatis.org//DTD Config 3.0//EN"
"http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
<typeAliases>
<package name="com.atguigu.mybatis.bean"/>
typeAliases>
<environments default="mysql_test">
<environment id="mysql_test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.atguigu.mybatis.mapper"/>
mappers>
configuration>
使用typeAlisaes标签设置类的别名:
<typeAliases>
<package name="com.atguigu.mybatis.bean"/>
typeAliases>
使用alias属性设置别名时,别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名。
以下为常见数据类型的别名:
基本数据类型: _基本数据类型
引用数据类型: 引用数据类型全小写
!](https://img-blog.csdnimg.cn/48565f78410c4e73b91763411df7f378.png)
使用mappers标签实现mapper接口和mapper映射文件的映射,用法如下:
<mappers>
<package name="com.atguigu.mybatis.mapper"/>
mappers>
以包为单位,将包下所有的映射文件引入核心配置文件时,需要注意:
- 此方式必须保证mapper接口和mapper映射文件必须在相同的包下
- mapper接口要和mapper映射文件的名字一致
在 File——>Settings——>Editor——>File and Code Templates 新建mybatis-config和mybatis-mapper模板文件,其格式如下
mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
<typeAliases>
<package name="com.xxx.entity"/>
typeAliases>
<environments default="company">
<environment id="company">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<package name="mappers"/>
mappers>
configuration>
以包为单位,将包下所有的映射文件引入核心配置文件时需要注意:
- 此方式必须保证mapper接口和mapper映射文件必须在相同的包下
- mapper接口要和mapper映射文件的名字一致
mybatis-mapper.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
mapper>
为了之后测试方便,可以借助自定义的SqlSessionUtil工具类简化测试:
package com.atguigu.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.IOException;
import java.io.InputStream;
public class SqlSessionUtil {
private static SqlSessionFactory factory;
private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();
static {
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
private static SqlSession getSqlSession(boolean isAutoCommit) {
SqlSession sqlSession = local.get();
if (sqlSession == null){
sqlSession = factory.openSession(isAutoCommit);
local.set(sqlSession);
}
return sqlSession;
}
public static SqlSession getSqlSession(){
return getSqlSession(false);
}
public static <T extends Object>T getMapper(Class<T> c){
SqlSession sqlSession = getSqlSession(true);
return sqlSession.getMapper(c);
}
}
${}
和#{}
字符串拼接
,#{}的本质就是占位符赋值
若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号
;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号
不涉及字符串用#{},涉及字符串拼接用${}
;
<select id="getUserByName" resultType="com.atguigu.pojo.User">
select * from t_user where username = #{username}
select>
<select id="getUserByName" resultType="com.atguigu.pojo.User">
select * from t_user
where username = '${username}'
select>
若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中
因此只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号。
使用arg或者param都行,要注意的是,arg是从arg0开始的,param是从param1开始的
<select id="getUserListByPage" resultType="com.atguigu.pojo.User">
select * from t_user
limit #{arg0}, #{arg1}
select>
<select id="getUserListByPage" resultType="com.atguigu.pojo.User">
select * from t_user
limit #{param1}, #{param2}
select>
通过${}和#{}访问map集合的键就可以获取相对应的值
,注意${}需要手动加单引号
<select id="getUserListByPage" resultType="com.atguigu.pojo.User">
select * from t_user
limit #{start}, #{pageSize}
select>
/**
* 获取User列表分页
*
* @throws IOException
*/
@Test
public void testGetUserListByPage() throws IOException {
UserMapper userMapper = SqlSessionUtil.getMapper(UserMapper.class);
HashMap<String,Integer> map = new HashMap<>();
map.put("start",0);
map.put("pageSize",2);
List<User> userList = userMapper.getUserListByPage(map);
System.out.println(userList);
}
访问实体类对象中的属性名获取属性值
,注意${}需要手动加单引号
<insert id="insertUser">
insert into t_user
values (#{id}, #{username}, #{password}, #{gender}, #{age}, #{email})
insert>
@Test
public void insertUser() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper userMapper = SqlSessionUtil.getMapper(UserMapper.class);
User user = new User(null, "李四", "1234", 16, "[email protected]", "女");
userMapper.insertUser(user);
}
可以通过@Param注解标识mapper接口中的方法参数
,此时,会将这些参数放在map集合中
只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号
<select id="getUserListByPage" resultType="com.atguigu.pojo.User">
select * from t_user
limit #{start}, #{pageSize}
select>
/**
* 获取User列表分页
*
* @throws IOException
*/
@Test
public void testGetUserListByPage() throws IOException {
UserMapper userMapper = SqlSessionUtil.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserListByPage(0, 2);
System.out.println(userList);
}
通过debug断点调试,逐步渗透分析到ParamNameResolver.java
显然,使用@Param标识参数以获取参数值,也是在底层通过自定义封装为map形式的参数。
建议分成两种情况进行处理
{password=123456, sex=男, id=1, age=23, username=admin}
/**
* 根据用户id查询用户信息
* @param id
* @return
*/
User getUserById(@Param("id") int id);
<select id="getUserById" resultType="User">
select * from t_user where id = #{id}
select>
注意:
- 查询的数据只有一条,实体类和集合接收都可以;
- 查询的数据有多条,只能使用集合接收,否则报错
/**
* 查询所有用户信息
* @return
*/
List<User> getUserList();
<select id="getUserList" resultType="User">
select * from t_user
select>
/**
* 查询用户的总记录数
* @return
* 在MyBatis中,对于Java中常用的类型都设置了类型别名
* 例如:java.lang.Integer-->int|integer
* 例如:int-->_int|_integer
* 例如:Map-->map,List-->list
*/
int getCount();
<select id="getCount" resultType="integer">
select count(*) from t_user;
select>
/**
* 根据id查询用户信息,封装为map集合
*/
Map<String,Object> getUserByIdToMap(@Param("id") Integer id);
<select id="getUserByIdToMap" resultType="map">
select * from t_user
where id = #{id}
select>
{password=123456, gender=男, id=1, age=22, [email protected], username=张三}
MyBatis会将查询到的数据按照key-value转为map集合,其中key为属性名,value=字段值
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取
*/
List<Map<String,Object>> getUserListToMap();
<select id="getAllUserToMap" resultType="map">
select * from t_user
select>
样例结果:
[{password=123456, gender=男, id=1, age=22, email=zhangsang@168.com, username=张三}, {password=1234, gender=女, id=2, age=16, email=12468965@qq.com, username=李四1}, {password=1234, gender=女, id=3, age=16, email=12468965@qq.com, username=李四2}, {password=1234, gender=女, id=5, age=16, email=12468965@qq.com, username=李四4}, {password=1234, gender=女, id=6, age=16, email=12468965@qq.com, username=李四5}]
/**
* 查询所有的用户信息,封装为map集合
* @MapKey("id") 表示以id为key,id对应的user信息为value
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,
* 并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合
*/
@MapKey("id")
Map<String,Object> getUserListToMap2();
<select id="getUserListToMap2" resultType="java.util.Map">
select * from t_user
select>
样例结果:
{
1={password=123456, gender=男, id=1, age=22, email=zhangsang@168.com, username=张三},
2={password=1234, gender=女, id=2, age=16, email=12468965@qq.com, username=李四1},
3={password=1234, gender=女, id=3, age=16, email=12468965@qq.com, username=李四2},
5={password=1234, gender=女, id=5, age=16, email=12468965@qq.com, username=李四4},
6={password=1234, gender=女, id=6, age=16, email=12468965@qq.com, username=李四5}
}
/**
* 根据用户名进行模糊查询
*/
List<User> getUserByLike(@Param("username") String username);
<select id="getUserByLike" resultType="User">
select * from t_user where username like "%"#{mohu}"%"
select>
select * from t_user where username like "%"#{mohu}"%"
是最常用的方式一:
delete from t_user where id in ('1,2,3')
,这样是将1,2,3
看做是一个整体,只有id为1,2,3
的数据会被删除。正确的语句应该是delete from t_user where id in (1,2,3)
,或者delete from t_user where id in ('1','2','3')
/**
* 根据id批量删除
* @param ids 形如 1,2
* @return
*/
int deleteMore(@Param("ids") String ids);
<delete id="deleteMore">
delete from t_user where id in (${ids})
delete>
@Test
public void testDeleteMore(){
SQLMapper mapper = SqlSessionUtil.getMapper(SQLMapper.class);
int i = mapper.deleteMore("10,11");
System.out.println(i);
}
方式二:
采用List传递待删除的数据的id,借助foreach实现批量删除的SQL语句
/**
* 根据存储待删除id的list批量删除
* @param ids
* @return
*/
int deleteMore2(@Param("ids") List<Integer> ids);
<delete id="deleteMore2">
delete from t_user
where id in
<foreach collection="ids" item="i" separator="," open="(" close=")">
#{i}
foreach>
delete>
@Test
public void testDeleteMore2(){
SQLMapper mapper = SqlSessionUtil.getMapper(SQLMapper.class);
int i = mapper.deleteMore2(Arrays.asList(9,12,13));
System.out.println(i);
}
/**
* 查询指定表中的数据
* @param tableName
* @return java.util.List
* @date 2022/2/27 14:41
*/
List<User> getUserByTable(@Param("tableName") String tableName);
<select id="getUserByTable" resultType="User">
select * from ${tableName}
select>
使用场景
在mapper.xml中设置两个属性
useGeneratedKeys
:设置使用自增的主键
keyProperty
:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
/**
* 添加用户信息
*
* @return
*/
int insertUser(SelectUser selectUser);
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user
values (#{id}, #{username}, #{password}, #{gender}, #{age}, #{email})
insert>
@Test
public void testInsertUser(){
SQLMapper mapper = SqlSessionUtil.getMapper(SQLMapper.class);
SelectUser selectUser = new SelectUser(null, "李四", "1234", 16, "[email protected]", "女");
mapper.insertUser(selectUser);
System.out.println(selectUser);
}
输出:
SelectUser(id=14, username=李四, password=1234, age=16, [email protected], gender=女)
可以看到,执行添加SQL后,实体类的id被赋值为添加的数据的主键
现在面临这样一个问题,实体类的empName属性对应着关系表中的emp_name字段,但直接返回时empName属性不会被emp_name字段正确赋值,出现了 empName=null 的情况。针对这个问题:
方式一:对emp_name字段起别名
<select id="getAllEmp" resultType="com.atguigu.pojo.Emp">
select eid, emp_name as empName, password, gender, age, email, did
from t_emp
select>
方式二:在mybatis配置文件中开启 驼峰命名自动映射mapUnderscoreToCamelCase
在mybatis-config.xml配置文件中添加如下代码:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
这种方法适用情形:字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)
接下来介绍第三种方法,自定义映射resultMap来解决上述实体类的属性与关系表的字段名不匹配问题。
resultMap:设置自定义映射
type
:查询的数据要映射的实体类的类型resultMap子标签:
主键
的映射关系普通字段
的映射关系实体类中的属性名
表中的字段名
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
<result property="empName" column="emp_name"/>
<result property="gender" column="gender" />
<result property="password" column="password"/>
resultMap>
<select id="getAllEmp" resultMap="empResultMap">
select eid, emp_name , password, gender, age, email, did
from t_emp
select>
查询员工信息以及员工所对应的部门信息
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Emp {
private Integer eid;
private String empName;
private String password;
private String gender;
private Integer age;
private String email;
private Dept dept;
}
<resultMap id="empAndDeptResultMap" type="Emp">
<id property="eid" column="eid"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
<result property="empName" column="emp_name"/>
<result property="gender" column="gender"/>
<result property="password" column="password"/>
<result property="dept.did" column="did" />
<result property="dept.deptName" column="dname"/>
resultMap>
<select id="getAllEmpAndDept" resultMap="empAndDeptResultMap">
select eid, emp_name, password, gender, age, email, e.did as did, dname
from t_emp as e
inner join t_department as d on d.did = e.did
select>
内连接、等值连接、左连接和右连接的区别
<resultMap id="empAndDeptResultMap2" type="Emp">
<id property="eid" column="eid"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
<result property="empName" column="emp_name"/>
<result property="gender" column="gender"/>
<result property="password" column="password"/>
<association property="dept" javaType="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dname"/>
association>
resultMap>
<select id="getAllEmpAndDept2" resultMap="empAndDeptResultMap2">
select eid, emp_name, password, gender, age, email, e.did as did, dname
from t_emp as e
inner join t_department as d on d.did = e.did
select>
//EmpMapper
/**
* 通过分步查询,员工及所对应的部门信息
* 分步查询第一步:查询员工信息
* @param
* @return com.atguigu.pojo.Emp
* @date 2022/2/27 20:17
*/
List<Emp> getAllEmpAndDept3();
<resultMap id="empAndDeptResultMap3" type="Emp">
<id property="eid" column="eid"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
<result property="empName" column="emp_name"/>
<result property="gender" column="gender"/>
<result property="password" column="password"/>
<association property="dept" select="com.atguigu.mapper.DeptMapper.getDeptById" column="did"/>
resultMap>
<select id="getAllEmpAndDept3" resultMap="empAndDeptResultMap3">
select eid, emp_name, password, gender, age, email, did
from t_emp
select>
//DeptMapper里的方法
/**
* 通过分步查询,员工及所对应的部门信息
* 分步查询第二步:通过did查询员工对应的部门信息
* @param
* @return com.atguigu.pojo.Emp
* @date 2022/2/27 20:23
*/
Dept getDeptById(@Param("did") Integer did);
<resultMap id="deptResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dname"/>
resultMap>
<select id="getDeptById" resultMap="deptResultMap">
select did, dname
from t_department
where did = #{did}
select>
去掉 Emp实体类中的dept属性,在Dept实体类中增加属性
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {
private Integer did;
private String deptName;
private List<Emp> empList;
}
<resultMap id="deptAndEmpResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dname"/>
<collection property="empList" ofType="Emp">
<id property="eid" column="eid"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
<result property="empName" column="emp_name"/>
<result property="gender" column="gender"/>
<result property="password" column="password"/>
collection>
resultMap>
<select id="getDeptList" resultMap="deptAndEmpResultMap">
select e.did, dname, eid, age, email, emp_name, gender, password
from t_department d
left outer join t_emp e on d.did = e.did
select>
/**
* 通过分步查询,查询部门及对应的所有员工信息
* 分步查询第一步:查询部门信息
* @param did
* @return com.atguigu.pojo.Dept
*/
List<Dept> getDeptList2();
<resultMap id="deptAndEmpResultMap2" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dname"/>
<association property="empList" select="com.atguigu.mapper.EmpMapper.getEmpListByDid" column="did"/>
resultMap>
<select id="getDeptList2" resultMap="deptAndEmpResultMap2">
select did, dname
from t_department
select>
/**
* 通过分步查询,查询部门及对应的所有员工信息
* 分步查询第二步:根据部门id查询部门中的所有员工
* @param did
*/
List<Emp> getEmpListByDid(@Param("did")Integer did);
<select id="getEmpListByDid" resultMap="empResultMap">
select eid, emp_name, password, gender, age, email, did
from t_emp
where did = #{did}
select>
association
和collection
中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
@Test
public void test2() {
DeptMapper mapper = SqlSessionUtil.getMapper(DeptMapper.class);
List<Dept> deptList = mapper.getDeptList2();
System.out.println(deptList);
}
@Test
public void test2() {
DeptMapper mapper = SqlSessionUtil.getMapper(DeptMapper.class);
List<Dept> deptList = mapper.getDeptList2();
for (Dept dept : deptList) {
System.out.println(dept);
System.out.println(dept.getEmpList());
}
}
开启后,需要用到查询dept的时候才会调用相应的SQL语句
<select id="getDeptList" resultMap="deptAndEmpResultMap">
select d.did, dname, eid, age, email, emp_name, gender, password
from t_department d
left outer join t_emp e on d.did = e.did
select>
<resultMap id="deptAndEmpResultMap2" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dname"/>
<association property="empList" select="com.atguigu.mapper.EmpMapper.getEmpListByDid" column="did" fetchType="lazy"/>
resultMap>
<select id="getDeptList2" resultMap="deptAndEmpResultMap2">
select did, dname
from t_department
select>
Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题
1=1
1=1
可以用来拼接and
语句,例如:当empName为null时select * from t_emp where and age = ? and email = ?
,此时where
会与and
连用,SQL语句会报错select * from t_emp where 1= 1 and age = ? and email = ?
,此时不报错
<select id="getEmpByIf" resultMap="com.atguigu.mapper.EmpMapper.empResultMap">
select * from t_emp where 1=1
<if test="empName != null and empName != ''">
emp_name = #{empName}
if>
<if test="age != null and age > 0">
and age = #{age}
if>
<if test="email != null and email != ''">
and email = #{email}
if>
select>
<select id="getEmpByWhere" resultMap="com.atguigu.mapper.EmpMapper.empResultMap">
select * from t_emp
<where>
<if test="empName != null and empName != ''">
emp_name = #{empName}
if>
<if test="age != null and age > 0">
and age = #{age}
if>
<if test="email != null and email != ''">
and email = #{email}
if>
where>
select>
<if test="empName != null and empName !=''">
emp_name = #{empName} and
if>
<if test="age != null and age !=''">
age = #{age}
if>
select * from t_emp
<select id="getEmpByTrim" resultMap="com.atguigu.mapper.EmpMapper.empResultMap">
select * from t_emp
<trim prefix="where" suffix=" order by eid desc ">
<if test="empName != null and empName != ''">
emp_name = #{empName}
if>
<if test="age != null and age > 0">
and age = #{age}
if>
<if test="email != null and email != ''">
and email = #{email}
if>
trim>
select>
//测试类
@Test
public void getEmpByCondition3() {
DynamicSQLMapper mapper = SqlSessionUtil.getMapper(DynamicSQLMapper.class);
List<Emp> empList = mapper.getEmpByCondition2(new Emp(null, "张三", "", "", 22, ""));
System.out.println(empList);
}
choose、when、otherwise
相当于if...else if..else
<select id="getEmpByChoose" resultMap="com.atguigu.mapper.EmpMapper.empResultMap">
select * from t_emp
<where>
<choose>
<when test="empName != null and empName != ''">
emp_name = #{empName}
when>
<when test="age != null and age > 0">
and age = #{age}
when>
<when test="email != null and email != ''">
and email = #{email}
when>
<otherwise>
did = 1
otherwise>
choose>
where>
select>
@Test
public void getEmpByChoose() {
DynamicSQLMapper mapper = SqlSessionUtil.getMapper(DynamicSQLMapper.class);
List<Emp> empList = mapper.getEmpByChoose(new Emp(null, "张三", "", "", 22, ""));
System.out.println(empList);
}
if a else if b else if c else d
,只会执行其中一个属性:
,
使用场景一:批量删除
/**
* 批量删除:foreach标签
*/
int deleteMore(@Param("ids")List<Integer> ids);
<delete id="deleteMore">
delete from t_emp
where eid in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
foreach>
delete>
@Test
public void deleteMore() {
DynamicSQLMapper mapper = SqlSessionUtil.getMapper(DynamicSQLMapper.class);
List<Integer> ids = Arrays.asList(12, 13, 14);
int i = mapper.deleteMore(ids);
System.out.println("i = " + i);
}
/**
* 批量插入:foreach标签
*/
int insertMore(@Param("empList")List<Emp> empList);
<insert id="insertMore">
insert into t_emp( emp_name, password, gender, age, email, did)
values
<foreach collection="empList" item="emp" separator="," close=";">
(#{emp.empName}, #{emp.password}, #{emp.gender}, #{emp.age}, #{emp.email}, 3)
foreach>
insert>
<!-- 使用foreach标签实现批量删除 -->
<delete id="deleteMore">
delete from t_emp
where eid in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
include
标签进行引入
标签
<sql id="empCloumns" >
eid, emp_name, password, gender, age, email, did
sql>
标签
<select id="getEmpList" resultMap="com.atguigu.mapper.EmpMapper.empResultMap">
select <include refid="empCloumns"/>
from t_emp
select>
一级缓存是SqlSession级别
的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问 ;默认开启
;只针对查询语句生效
;样例:
@Test
public void testFirstLevelCache(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> allEmp = mapper.getEmpList();
System.out.println(allEmp);
DynamicSQLMapper mapper2 = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> allEmp2 = mapper2.getEmpList();
System.out.println(allEmp2);
}
可以看出,虽然调用了两次列表查询,但实际只执行了一次SQL查询。
使一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession两次查询期间执行了任何一次增删改操作
- 同一个SqlSession两次查询期间手动清空了缓存,调用SqlSession实例的closeCache方法
二级缓存是SqlSessionFactory级别
,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取二级缓存开启的条件
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
<cache />
/**
* 测试二级缓存
*/
@Test
public void testSecondLevelCache() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession();
DynamicSQLMapper mapper1 = sqlSession1.getMapper(DynamicSQLMapper.class);
List<Emp> empList1 = mapper1.getEmpList();
System.out.println(empList1);
// 二级缓存必须在SqlSession关闭或提交之后有效
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
DynamicSQLMapper mapper2 = sqlSession2.getMapper(DynamicSQLMapper.class);
List<Emp> empList2 = mapper2.getEmpList();
System.out.println(empList2);
}
cache标签
可以设置一些属性eviction
属性:缓存回收策略
默认的缓存回收策略
。flushInterval
属性:刷新间隔,单位毫秒
默认情况是不设置
,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新size
属性:引用数目,正整数
readOnly
属性:只读,true/false,默认是false
**MyBatis缓存查询的顺序:**二级缓存 --> 一级缓存 --> 数据库
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.1version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>
各个jar包的功能
jar包名称 | 作用 |
---|---|
mybatis-ehcache | Mybatis和EHCache的整合包 |
ehcache | EHCache核心包 |
slf4j-api | SLF4J日志门面包 |
logback-classic | 支持SLF4J门面接口的一个具体实现 |
ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
defaultCache>
ehcache>
EHCache的配置文件的属性说明:
属性名 | 是否必须 | 作用 |
---|---|---|
maxElementsInMemory | 是 | 在内存中缓存的element的最大数目 |
maxElementsOnDisk | 是 | 在磁盘上缓存的element的最大数目,若是0表示无穷大 |
eternal | 是 | 设定缓存的elements是否永远不过期。 如果为true,则缓存的数据始终有效, 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断 |
overflowToDisk | 是 | 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上 |
timeToIdleSeconds | 否 | 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大 |
timeToLiveSeconds | 否 | 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 |
diskSpoolBufferSizeMB | 否 | DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区 |
diskPersistent | 否 | 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false |
diskExpiryThreadIntervalSeconds | 否 | 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s, 相应的线程会进行一次EhCache中数据的清理工作 |
memoryStoreEvictionPolicy | 否 | 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。 默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出 |
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
logback.xml
,名字固定,不可改变
<configuration debug="true">
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%npattern>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
root>
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
configuration>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.9version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.2version>
<configuration>
<overwrite>trueoverwrite>
configuration>
<dependencies>
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
dependencies>
plugin>
plugins>
build>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<typeAliases>
<package name=""/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<package name=""/>
mappers>
configuration>
generatorConfig.xml
DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="jdbc.properties"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<property name="javaFileEncoding" value="UTF-8"/>
<commentGenerator>
<property name="suppressAllComments" value="true" />
commentGenerator>
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
<property name="nullCatalogMeansCurrent" value="true"/>
jdbcConnection>
<javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
javaModelGenerator>
<sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
javaClientGenerator>
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_department" domainObjectName="Dept"/>
context>
generatorConfiguration>
如果出现报错:Exception getting JDBC Driver
,可能是pom.xml中,数据库驱动配置错误
selectByExample
:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据example.createCriteria().xxx
:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系example.or().xxx
:将之前添加的条件通过or拼接其他条件 @Test
public void test() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 查询所有数据
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.selectByExample(null);
empList.forEach(System.out::println);
System.out.println("********************");
// 根据条件查询
EmpExample empExample = new EmpExample();
// 姓名为张三,年龄大于20
empExample.createCriteria().andEmpNameEqualTo("张三").andAgeGreaterThan(20);
//或者did不为空
empExample.or().andDidIsNotNull();
List<Emp> emps = empMapper.selectByExample(empExample);
emps.forEach(System.out::println);
}
DEBUG 08-10 21:32:18,431 ==> Preparing: select eid, emp_name, password, gender, age, email, did from t_emp WHERE ( emp_name = ? and age > ? ) or( did is not null ) (BaseJdbcLogger.java:137)
DEBUG 08-10 21:32:18,432 > Parameters: 张三(String), 20(Integer) (BaseJdbcLogger.java:137)
DEBUG 08-10 21:32:18,435 < Total: 11 (BaseJdbcLogger.java:137)
updateByPrimaryKey
:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null
mapper.updateByPrimaryKey(new Emp(1,"admin",22,null,"[email protected]",3));
updateByPrimaryKeySelective()
:通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段
mapper.updateByPrimaryKeySelective(new Emp(2,"admin2",22,null,"[email protected]",3));
@Test
public void test2() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// updateByPrimaryKey通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null
// empMapper.updateByPrimaryKey(new Emp(11,"Sakura","123456",null,11,null,1));
// 通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段
empMapper.updateByPrimaryKeySelective(new Emp(11,"Sakura","123456",null,11,null,1));
}
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.0version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
PageHelper.startPage(int pageNum, int pageSize)
开启分页功能
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//访问第一页,每页四条数据
PageHelper.startPage(1,4);
List<Emp> emps = mapper.selectByExample(null);
emps.forEach(System.out::println);
}
方法一:直接输出
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//访问第一页,每页四条数据
Page<Object> page = PageHelper.startPage(1, 4);
// 查询全部数据
List<Emp> emps = mapper.selectByExample(null);
//在查询到List集合后,打印分页数据
System.out.println(page);
}
分页相关数据:
Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}]
方法二使用PageInfo
PageInfo pageInfo = new PageInfo<>(List list, intnavigatePages)
获取分页相关数据
PageHelper.startPage需要放在查询语句的上面且紧邻
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
PageHelper.startPage(1, 4);
List<Emp> emps = mapper.selectByExample(null);
PageInfo<Emp> page = new PageInfo<>(emps,5);
System.out.println(page);
}
分页相关数据:
PageInfo{
pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=8, pages=2,
list=Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}],
prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}
其中list中的数据等同于方法一中直接输出的page数据
常用数据: