因为编辑器不互通,所以可以直接打开有道云看
有道云链接


  1. Mybatis的初入
    创建Maven项目工程,因为Mybatis属于数据访问层的操作,我们需要引入相关依赖
    mysql mysql-connector-java 8.0.29 org.mybatis mybatis 3.5.9 junit junit 4.13.2 test org.projectlombok lombok 1.18.24

因为是对于数据库做操作,所以需要有一个对应的数据库。数据库名称为mybatis。在数据库里新建一个表,叫做table_users。
create table table_users(
id int(20) primary key auto_increment,
username varchar(30),
password varchar(30),
age int(10),
gender char,
email varchar(50)
);

在创建好数据库以后,要有一个与之对应的实体类。也就是User类。可以把放置在Pojo包下。User类代码如下。(有lombok)

package mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {

private Integer id;private String username;private String password;private Integer age;private String gender;private String email;

}

创建mybatis的核心配置文件。

一般来说,配置文件分为mapper映射文件,和mybatis的核心配置文件。 mybatis的核心配置文件,用来配置数据库的连接信息,mybatis的全局配置等等。针对于配置文件的命名规范,myabtis并没有什么强制性要求,不过推荐把mybatis的核心配置文件叫做 mybatis-config.xml。一般来说,该文件位于maven项目的 src/resource文件目录下。

Mybatis-config.xml 配置模板

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 映射 -->
<mappers></mappers>

在创建好mybatis-config.xml之后,我们需要有一个Mapper接口。

package mybatis.mapper;

public interface UserMapper {

int insertUser();

}

然后我们需要有一个对应Mapper接口的Mapper.xml映射文件。namespace对应的是Mapper接口,id对应的是接口内的方法名称

<?xml version="1.0" encoding="UTF-8" ?>

<insert id="insertUser">insert into table_users value (null, 'jack', '123513', 15, '男', '878035748@qq.com')
</insert>

剩下内容均在测试类内完成。

import mybatis.mapper.UserMapper;
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;

public class MybatisTest {

@Test
public void helloMybatis() {try {// 通过mybatis提供的Resources获取到输入流配置文件。InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");// 通过sqlSession工厂来取出会话, openSession设置为true自动提交事务SqlSession sqlSession = (SqlSession) new SqlSessionFactoryBuilder().build(resourceAsStream).openSession(true);// 动态代理,获取Mapper实现UserMapper mapper = sqlSession.getMapper(UserMapper.class);// 执行方法System.out.println("执行结果条数为: " + mapper.insertUser());// 释放资源sqlSession.close();} catch (IOException e) {e.printStackTrace();}}

}

  1. Mybatis增删改查操作以及抽取工具类
    抽取工具类Util
    package mybatis.uitl;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

public class SqlSessionUtil {

public static SqlSession getSqlSession() {try {return new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession(true);} catch (IOException e) {e.printStackTrace();}return null;
}

}

2.1 Mybatis增加操作

UserMapper.class
public interface UserMapper {
int insertUser();
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<insert id="insertUser">insert into table_users value (null, 'jack', '123513', 15, '男', '878035748@qq.com')
</insert>

mybatis-config.xml

test测试类
@Test
public void helloMybatis() {

try {// 通过mybatis提供的Resources获取到输入流配置文件。InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");// 通过sqlSession工厂来取出会话, openSession设置为true自动提交事务SqlSession sqlSession = (SqlSession) new SqlSessionFactoryBuilder().build(resourceAsStream).openSession(true);// 动态代理,获取Mapper实现UserMapper mapper = sqlSession.getMapper(UserMapper.class);// 执行方法System.out.println("执行结果条数为: " + mapper.insertUser());// 释放资源sqlSession.close();} catch (IOException e) {e.printStackTrace();}

}

2.2 Mybatis修改操作

UserMapper.class
public interface UserMapper {
void updateUser();
}

UserMapper.xml

update table_users set username = ‘root’, password = ‘123’ where id = 2

test测试类
@Test
public void updateUsers() {

SqlSession sqlSession = SqlSessionUtil.getSqlSession();assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.updateUser();

}

2.3 Mybatis删除操作

UserMapper.class
public interface UserMapper{
void deleteUser();
}

UserMapper.xml

delete from table_users where id = 3’

test测试类
@Test
public void deleteUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser();
}

2.4 Mybatis查询
当表内的字段能和实体类一一对应的时候,查询多条数据,也可以返回值使用该实体类。进行封装。
UserMapper.class
public interface UserMapper {
User getUser();
List getAllUser();
}

UserMapper.xml

select * from users where id = 1

select * from users

test测试代码
@Test
public void selectUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.selectUser());
}

@Test
public void selectAllUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.selectAllUsers().forEach(System.out::println);
}

  1. Mybatis核心配置文件

3.1 Mybatis核心配置文件标签优先级
(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)

3.2 Mybatis核心配置文件之Environments

environments 配置连接数据库的环境。在environments下面,可以有很多个不同的 envrionment。每一个environment都有一个对应的数据库环境。在开发中,不可能同时使用多个数据库环境。所以,在environments中有一个属性。default。可以通过default绑定environment的id与之对应。

在 environment 中,id标识是唯一的,每一个id对应一个数据库操作环境。并且它拥有子标签 TeanscationManager 事务处理器,一般来说,使用JDBC支持的事务开启。采用JDBC原生的事务管理方式。
dataSource 数据源。里面设置数据库链接相关的内容,驱动,url, username, password。 在dataSource中,有一个属性type。这里是选择数据源获取的方式,上面代码选择了池类型。
3.3 在核心配置文件中引入properties文件
如果想把dataSource中的数据源信息抽取出去,改为外部文件配置。解耦。可以采用一个新的标签。 在该标签内,有一个resource属性。对应你需要引入的properties文件。如下

然后在dataSource中,采用 这 种 方 式 , 来 对 数 据 进 行 引 入 。 例 如 , 我 j d b c . p r o p e r t i e s 中 的 一 些 键 值 对 是 这 样 的 j d b c . d r i v e r = c o m . m y s q l . c j . j d b c . D r i v e r j d b c . u s e r n a m e = r o o t j d b c . p a s s w o r d = r o o t j d b c . u r l = j d b c : m y s q l : / / l o c a l h o s t : 3306 / m y b a t i s ? s e r v e r T i m e z o n e = U T C 则 我 在 d a t a S o u r c e 中 采 用 这 种 方 式 引 入 < d a t a S o u r c e t y p e = " P O O L E D " > < ! − − 数 据 库 驱 动 − − > < p r o p e r t y n a m e = " d r i v e r " v a l u e = " {} 这种方式,来对数据进行引入。例如,我jdbc.properties中的一些键值对是这样的 jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.username=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC 则我在dataSource中采用这种方式引入 <dataSource type="POOLED"> <!-- 数据库驱动 --> <property name="driver" value=" 这种方式,来对数据进行引入。例如,我jdbc.properties中的一些键值对是这样的jdbc.driver=com.mysql.cj.jdbc.Driverjdbc.username=rootjdbc.password=rootjdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC则我在dataSource中采用这种方式引入<dataSourcetype="POOLED"><!−−数据库驱动−−><propertyname="driver"value="{jdbc.driver}"/>

3.4 别名配置TypeAliases
在很多时候用全包类名很不方便,比如如下场景。

select * from table_users where id = 2

select * from table_users 可以看到在返回值类型中,采用的是全包类名的样式,此时就可以设置别名来解决繁杂问题。需要注意的是标签和标签之间的对应位置。 这样,就配置好了一个别名,其中,type属性的意义是表示配置的类型,alias属性的意义表示的是别名的名称,在上述配置完成后,意义表达为。我要把mybatis.pojo包下的User类的名字叫做 user。 以后我使用user,就表示的是 mybatis.pojo.User。同样,优化过后的mapper.xml文件就是如下 select * from table_users where id = 2 select * from table_users 还有另外一种情况,只设置type,不设置alias那么他就会默认使用类名,且不区分大小写。如下 3.5 通过包来设置别名 在通过这种package来设置的话,在该包底下所有的内容,都会变成上述类名方式,大小写且不区分。

3.6 Mybatis核心配置文件之Mappers
用来映射Mapper配置文件的位置,有不同的方式,经典的是逐个配置如下。

通过mapper标签,来一个一个配置对应Mpaaer.xml的位置,但是同样他也有包扫描。 但是有两个注意点! 1. Mapper.xml所在的路径必须和Mapper.interface所在的路径一致。 2. Mapper.xml 和对应的接口 Mapper.class 文件名称必须一致。

  1. Mybatis获取参数值
    Mybatis提供了两种获取参数的方式, ${} 的本意是字符串拼接 , #{} 的本意类似于占位符,可以避免sql注入。

4.1 单个字面量类型的参数获取
字面量对应变量。可以理解为单个变量的获取。也就是说 基本数据类型,字符串,对应的包装类型等。
仅仅展示Mapper.xml 和 Test的内容即可理解

select * from table_users where username = #{username}

mapper.getUserByUsername(“root”)

需要注意的是,这里并不打算采用$符号,因为本来就是需要防止sql注入的。并且。在xml中的 {} 内,并不一定是写username,随便写什么都可以,它仅仅是存在占位的作用,但是为了做到见名知意,最好和Interface中的参数一致。

4.2 多个字面量类型的参数获取
同上内容,只不过由一个变成多个。需要注意的是。变成多个后,mybatis会把其封装成Map集合,获取你的参数可以通过键值对的方式来获取,mybatis提供了两种方式。
第一种是: arg0,arg1, arg2, arg3… 第二种是, param1, param2, param3…

接口内代码内容

public interface UserMapper {
User checkLogin(String username, String password);
}
Mapper.xml内容

select * from table_users where username = #{param1} and password = #{param2}

或者如下

select * from table_users where username = #{arg0} and password = #{arg1}

test内容
@Test
public void test2() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.checkLogin("root", "123"));
// 输出结果
// User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com)

}

4.3 通过Map集合的方式获取多个参数
在4.2中,获取的多个参数并不能自己定义kay值,需要按照mybatis提供的两种key来获取,一个是arg,一个是param。如果想要自定义key,则我们可以自己去写一个Map对象,然后即可使用自己的key来进行获取,不好的一点就是。需要手动进行数据pus。
interface

public interface UserMapper {
User checkLoginByMap(Map<String, Object> map);
}
Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<select id="checkLoginByMap" resultType="User">select * from table_users where username = #{username} and password = #{password}
</select>

test public void test3() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String, Object> map = new HashMap<>();map.put("username", "root");
map.put("password", "123");System.out.println(mapper.checkLoginByMap(map));

}

4.4 获取实体对象内的参数
若有一个实体类,实体类内有成员变量。成员变量和属性并非一个东西。什么是属性呢,把成员变量的对应的Get和Set方法,去掉get和set,剩下的全小写。即为属性名称。比如
有一个id的成员变量的get/set方法为 getId, setId, 则属性名称则是 id。
而Mybatis获取实体对象内的参数是通过属性名称来获取的。代码如下。
interface
void insertUser(User user);
Mapper.xml

insert into table_users values(null, #{username}, #{password}, #{age}, #{gender}, #{email})

test
@Test
public void test4() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(null, "admin", "123456", 16, "男", "12386@qq.com");mapper.insertUser(user);

}

4.5 @Param 注解指定Map中key的名称
相对于4.2中,使用 param1 2 3 这种方式,@param可以直接在接口内把参数名称定义好。在map中额外增加一个以 param中 value值的key,届时可以通过key来取value。除此之外,arg 和 param的方式 仍然可用。
interface
User checkLoginByParam(@Param(“username”) String username, @Param(“password”) String password);
Mapper.xml

select * from table_users where username = #{username} and password = #{password}

test
@Test
public void test5() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);System.out.println(mapper.checkLoginByParam("root", "123"));

}

  1. Mybatis的各种查询功能
    在查询前,一定要清楚你自己查询出来的东西是什么,是一个实体对象,还是一个字面量,还是什么什么的。
    5.1 查询单个实体对象或者多个实体类对象
    若查询的结果为一条时,我们可以以实体类来作为返回结果,若查询的语句为多条时,我们不能以实体类来作为返回结果,需要一个集合容器,因为如果使用实体类作为返回结果,则底层调用的方法为 SqlSession.SelectOne。这时候去获取多条数据,则报错。而使用List集合作为返回对象时,则可获取一条,也可获取多条。
    其实该功能在上面第一次查询时已经使用过。不多讲。直接结合上面内容写代码。
    UserSelectMapper.interface
    package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserSelectMapper {

User selectUserById(@Param("id") Integer id);List<User> selectAllUsers();

}
UserSelectMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 查询单个实体对象 根据id -->
<select id="selectUserById" resultType="User">select * from table_users where id = #{id}
</select><!-- 查询多个实体对象 -->
<select id="selectAllUsers" resultType="User">select * from table_users
</select>

Test @Test public void test1() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);System.out.println(mapper.selectUserById(2));
// User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com)System.out.println(mapper.selectAllUsers());
/*
[User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com),
User(id=4, username=jack, password=123513, age=15, gender=男, email=878035748@qq.com),User(id=5, username=admin, password=123456, age=16, gender=男, email=12386@qq.com)]
*/

}

5.2 查询单行单列数据信息
就是查询某列的平均值(avg),总条数啊(count)等等这些内容。在查询前,我们需要清楚的知道返回值类型应该包装成什么样子,例如。查询总条数,我返回的一定是一个整数类型,不可能返回小数类型。那我就可以使用Integer来表示,如果查询的是avg,则我可以用Double来表示。
在Mybatis中,官方已经为常用的一些包装对象。基本数据类型设置好了别名。具体如下。
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名映射的类型_bytebyte_longlong_shortshort_intint_integerint_doubledouble_floatfloat_booleanbooleanstringStringbyteBytelongLongshortShortintIntegerintegerIntegerdoubleDoublefloatFloatbooleanBooleandateDatedecimalBigDecimalbigdecimalBigDecimalobjectObjectmapMaphashmapHashMaplistListarraylistArrayListcollectionCollectioniteratorIterator

下面先写一个案例,展示查询数据库内总条数为多少。
UserSelectMapper.interface
public interface UserSelectMapper {
Integer selectCount();
}
UserServletMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 查询数据库内总条数 -->
<select id="selectCount" resultType="integer">select count(*) from table_users
</select>

Test @Test public void test2() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);System.out.println(mapper.selectCount());

}
5.3 查出的结果以Map集合的形式返回封装
使用Map集合以应对于数据库查询出来的内容中,并没有与之对应的实体类对象。则可以使用map集合来返回。以后很常用。
5.3.1 以单个实体对象返回Map中
当以Map<> 对象的形式返回,底层仍然调用的是selectOne。
Mapper.interface
Map<String, Object> getOneUsersByMap(@Param(“id”) Integer id);
Mapper.xml

select * from table_users where id = #{id}

Test
@Test
public void test3() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);Map<String, Object> oneUsersByMap = mapper.getOneUsersByMap(2);System.out.println(oneUsersByMap);

}
5.3.2 以多个实体对象返回Map中
在获取多个实体对象到Map时,返回的是多个Map集合,自然,需要找一个可以存放Map容器的东西,也就是List<Map<>>。
Mapper.interface
List<Map<String , Object>> getAllUsersByMap();
Mapper.xml

select * from table_users

Test
@Test
public void test4() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);List<Map<String, Object>> allUsersByMap = mapper.getAllUsersByMap();allUsersByMap.forEach(System.out::println);/*
{password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root}
{password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack}
{password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}*/

}

5.3.3 @MapKey
若不想把Map位置于集合中,则可以使用@MapKey来解决,指定一个查询出来的数据的名称作为map返回数据的key。举例说明。
{password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root}
{password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack}
{password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}
查出来三条数据,接口为 Map<String, Object> getAllUsersByMap();
此时如果硬要查,则报错。无法把三条Map封装进一个Map中,因为他们没有key,则@MApKey则类似于Map中套Map,设置了一个key。于是大概就变成了。
Map<String, Map<String, Object>> 这种格式。则相当于指定了一个属性作为map的key
举例。
Interface
@MapKey(“id”)
Map<String, Object > getAllUsers();
Xml

select * from table_users

Test
@Test
public void test5() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);System.out.println(mapper.getAllUsers());//{2={password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root},
// 4={password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack},
// 5={password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}}

}

  1. Mybatis处理模糊查询
    模糊查询不可以直接使用#{}来进行处理,因为 like %#{??}%’ 解析后会变为占位符, like ‘%?%’ 则,此时会直接的把他当作为字符串,而不是占位符,然mybatis找不到占位符,则会报错。
    有三种解决方式, 直接写xml内的sql,其他就忽略了
    6.1 采用字符串拼接方式
    select * from table_users where username like ‘%${value}%’
    6.2 采用sql内置函数拼接
    select * from table_users where username like concat(‘%’, #{value}, ‘%’})
    6.3 采用双引号拼接(最常用的方式)
    select * from table_users where username like “%”#{value}“%”
    6.4 三种示例
    interface
    package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface SpecialMapper {

List<User > getUserOne(@Param("value") String value);List<User > getUserTwo(@Param("value") String value);List<User > getUserThree(@Param("value") String value);

}
mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<select id="getUserOne" resultType="user">select * from table_users where email like '%${value}%'
</select><select id="getUserTwo" resultType="user">select * from table_users where email like concat('%', #{value}, '%')
</select><select id="getUserThree" resultType="user">select * from table_users where email like "%"#{value}"%"
</select>

Test import mybatis.mappers.SpecialMapper; import mybatis.pojo.User; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

import java.util.List;

public class SpecialMapperTest {

@Test
public void test1() {SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);List<User> userOne = mapper.getUserOne("8");userOne.forEach(System.out::println);}@Test
public void test2() {SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);List<User> userTwo = mapper.getUserTwo("8");userTwo.forEach(System.out::println);}@Test
public void test3() {SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);List<User> userThree = mapper.getUserThree("8");userThree.forEach(System.out::println);}

}

  1. 特殊的一些使用方法
    7.1 Mybatis批量删除简单使用
    批量删除在sql中一般有两种表达方式,一种是通过or,一种是通过in(),在还没有学习动态sql之前,是没办法做到or的。所以使用in函数来进行批量删除。
    在sql中,假设需要删除id为 1,2,3的三条sql,则需要
    delete from table_users where id in(1, 2, 3)
    也就是说,在括号内的,并不能是字符串,在mysql5版本,可以是字符串,但是他删除的则是开头的第一位数,无论你删除几遍,也是第一位数。所以我们并不能使用占位符的形式来进行拼接,也就是#{}的形式,我们需要使用拼接形式也就是${}
    Interface
    package mybatis.mappers;

import org.apache.ibatis.annotations.Param;

public interface BatchDeletionMapper {

void deleteBatch(@Param("sqlIn") String sqlIn);

}

Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<delete id="deleteBatch">delete from table_users where id in(${sqlIn})
</delete>

Test import mybatis.mappers.BatchDeletionMapper; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

public class BatchDeletionMapperTest {

@Test
public void test1() {SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;BatchDeletionMapper mapper = sqlSession.getMapper(BatchDeletionMapper.class);mapper.deleteBatch("8, 9");}

}

7.2 Mybatis动态设置表名
在这里其实也就是一个#和$ 的区别,因为查询表的sql语句如下
select * from [table]
但是 table是不允许有字符串的,我们仍然需要 ${} 来进行字面量获取。
该功能用途大致为,有一个用户表,有一个vip表,字段一样,根据传回来的信息,来查询对应的表。
Interface
package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface GetTableNameMapper {

List<User > getTableName(@Param("tableName") String tableName);

}

Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<delete id="deleteBatch">delete from table_users where id in(${sqlIn})
</delete>

Test import mybatis.mappers.GetTableNameMapper; import mybatis.pojo.User; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

import java.util.List;

public class GetTableNameTest {

@Test
public void test1() {SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;GetTableNameMapper mapper = sqlSession.getMapper(GetTableNameMapper.class);List<User> table_users = mapper.getTableName("table_users");table_users.forEach(System.out::println);}

}

7.3 添加功能获取自增的主键
因为添加方式的返回值,都是固定的,包括删除喝修改,都是受影响的条数,那么就会把返回自增的主键值,放在实体对象内。比如id。需要在xml中开启两个属性,一个是

useGeneratedKeys=“true”

keyProperty=“id”
Interface
package mybatis.mappers;

import mybatis.pojo.User;

public interface GetAutoKeyMapper {

void insertUser(User user);

}
Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into table_users values(NULL, #{username}, #{password}, #{age}, #{gender}, #{email})
</insert>

Test 1

7.4 使用全局配置处理字段名和属性名不一致的情况
大致意思是,Java的命名规则为驼峰法, 在mysql中字段命名规则为xxx_xxx,导致Java成员变量和mysql字段名称不一致,无法查询出内容,有两种解决方式。
第一种,使用mysql,在查询的时候起别名。

select emp_id empId, emp_name empName, age, gender from table_emp where emp_id = #{id}

第二种方式,直接在全局配置内配置setting。开启自动驼峰映射

<setting name="mapUnderscoreToCamelCase" value="true"/>

需要注意的是,要满足一定规则,也就是 emp_id --> empId, emp_name --> empName

7.5 使用ResultMap处理7.4的情况

这种属于自定义来自己指定内容,直接上代码就能看明白
Interface
Emp selectEmpByIdButIsResultMap(@Param(“id”) Integer id);
Mapper.xml

select * from table_emp where emp_id = #{id} 在Select标签中,也不再是resultType,返回值类型了,变成了 resultMap。resultMap的属性值为新标签的id。 在resultMap标签中,id是标识,type要处理哪个类的映射。内部目前用到的,id标签,表示主键。剩下的result表示普通字段的对应。 column属性,是在数据库内的字段名称 property属性,是对应的实体类属性

  1. 多表(连表)查询
    8.1 使用联级处理多对一的映射关系
    Interfac
    Emp selectEmpAndDept(@Param(“id”) Integer id);
    Mapper.xml

select * from table_emp left join table_dept on table_emp.dept_id = table_dept.dept_id where table_emp.emp_id = #{id} Test @Test public void test3() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);System.out.println(mapper.selectEmpAndDept(1));

}

8.2 使用association处理多对一的映射关系
association是专门用来处理多对一的映射关系。主要用来处理,实体类类型的属性。
其实说白了就是套娃。把属性当成一个对象,然后对象内在设置属性。

property表示对应的属性名称叫什么,JavaType表示你要对什么类型进行处理。

select * from table_emp left join table_dept on table_emp.dept_id = table_dept.dept_id where table_emp.emp_id = #{id} 其余的和8.1一样。Test @Test public void test3() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);System.out.println(mapper.selectEmpAndDept(1));

}

8.3 使用分步查询处理多对一的映射关系

第一步,首先先查出来整个emp表内的数据,得到dept_id
Emp stepByStepSelectByEmp(@Param(“id”) Integer id);
xml

select * from table_emp where emp_id = #{id} 此时,对于 association标签内的属性,下面会详细解释。 然后进行第二步,查询出来所有的部门表内的数据,也就是部门id和部门name。 Dept stepByStepSelectByDept(@Param("id") Integer deptId); xml select * from table_dept where dept_id = #{id} 此时,就可以对应起来了,在上面association标签内,property依然是属性。select为查询方法需要查出来的内容,也就是现在这个查询的唯一标识。column是查出来需要下次查询的字段。 测试方法 @Test public void test4() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);System.out.println(mapper.stepByStepSelectByEmp(1));

}

8.3.1 分布查询的优点-延迟加载

lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。true | falsefalseaggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
延迟加载就是按需加载,举上述例子来说,假设你只需要一个员工Name,则只会执行一条Sql,也就是
select * from table_emp where id = ?
然后返回给你对应的员工名称。与之关联的dept的sql则不会执行,因为没有用到。
开启该功能的前提是,在全局配置文件mybatis-config.xml中的setting标签内设置 lazyLoadingEnabled 为 true。
aggressiveLazyLoading则和该属性相反,他一旦设置为true,则会默认全部加载,哪怕lazyLoadingEnabled也为true。他俩一般一起出现。若全局配置懒加载,但是有部分的sql想要完全加载,也是有办法的。如下

select * from table_emp where emp_id = #{id}

在相对应关联的 association中设置 fetchType为eager,则为开启全部加载,与之对应还有一个lazy,则为懒加载。

8.4 通过collection来处理一对多的映射关系
首先在实体类内肯定有改变,因为是一对多,所以肯定在实体类中有对多的集合。
package mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {

private Integer deptId;private String deptName;private List<Emp > empList;

}

其实一对多就是把东西塞到了集合里,上代码然后解释。
Interface
Dept getDeptAndEmpByDeptId(@Param(“id”) Integer deptId);
Mapper.xml

select * from table_dept left join table_emp on table_dept.dept_id = table_emp.dept_id where table_dept.dept_id = #{id}; Test @Test public void test5() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);System.out.println(mapper.getDeptAndEmpByDeptId(1));

}
结果
Dept(deptId=1, deptName=A, empList=[Emp(empId=1, empName=张三, age=19, gender=男, dept=null), Emp(empId=6, empName=郭八, age=15, gender=男, dept=null), Emp(empId=7, empName=安九, age=18, gender=男, dept=null)])
其实和多对一一样,但是从association换成了collection,然后以前是javaType,但是collection中是ofTpye,也就是集合内是什么类型的对象。写为emp即可。

8.5 使用分布查询来查询一对多的关系
和多对一是一样的,还是一套模板,只需要搞清楚他们之间的关系即可
DeptMapper.interface
Dept getDeptAndEmpByStepOne(@Param(“deptId”) Integer deptId);
DeptMapper.xml

select * from table_dept where dept_id = #{deptId} EmpMapper.interface List getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId); EmpMapper.xml select * from table_emp where dept_id = #{deptId} Test @Test public void test6() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);System.out.println(mapper.getDeptAndEmpByStepOne(1));

}
结果
Dept(deptId=1, deptName=A, empList=[Emp(empId=1, empName=张三, age=19, gender=男, dept=null), Emp(empId=6, empName=郭八, age=15, gender=男, dept=null), Emp(empId=7, empName=安九, age=18, gender=男, dept=null)])

  1. 动态SQL
    9.1 搭建环境
    在原有的基础配置上,不变,清空所有的内容,留下util,创建pojo。且只有一个Emp

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Emp {

private Integer empId;private String empName;private Integer age;private String gender;

}

然后创建Mapper和对应的Xml 分别为
DynamicMapper.interface
DynamicMapper.xml
里面仅有最基础的内容。

9.2 if标签
根据对象条件查询出所对应的内容、
Mapper.interface
// 根据条件查询,不确定有几个对象。所以用List集合来装载,多条件肯定是根据Emp字段来查询所以传入对象
List getEmpByCondition(Emp emp);
Mapper.xml

select * from table_emp where

emp_name = #{empName}

if是根据test属性内条件。来决定是否拼接if标签内的内容。 因为我们上面传入的是一个Emp对象。则test内可以直接使用emp对象内的属性来进行判断。第一个,判断是否为空。第二个,判断是否为空字符。如果都不是,则可以拼接内容,拼接为以下
select * from table_emp where emp_name = ?;

9.3 where 标签
9.3.1 (1=1)
在if语句中,有一种情况,就是多个if的情况下。会出现这个情况
select * from table_emp where

emp_name = #{empName}

and age = #{age}

假设,第一个if不成立,那么第二个if成立,就会直接拼接在where后面
select * from table_emp where and age = ?;
则是sql语句直接报错。如果想要解决这种情况,有两种办法,在前面接上一个永远成立的条件。并且把if标签内全部加上and
select * from table_emp where 1 = 1

and emp_name = #{empName}

and age = #{age}

这种情况,可以解决这种问题,但是在mybatis中,提供了一个where标签

9.3.2 where
select * from table_emp where

emp_name = #{empName}

and age = #{age}

还是这个sql语句,如果需要她不报错,则可以在所有if的最外层,套上一个where。并且在sql中去掉where关键字
select * from table_emp

emp_name = #{empName}

and age = #{age}

如果,第一个if成立,则会自动在后面加上where关键字,然后拼接第一个if内的内容。
如果还是上述情况,则会自动去除age前面的 and关键字。变为。
select * from table_emp where age = ?;
当两个条件都不满足的时候,则不会生成任何内容。

9.4 trim标签
暂时感觉where好用。以后在说
prefix,suffix在标签中内容前面或者后面添加指定内容。
prefixOverrides, suffixOverrides在标签前面或者后面去除指定内容。

9.5 choose,when,otherwise
就是if elseif,else,只不过结构是这样的,在choose内没有属性。从when开始。

9.6 forEach标签
使用批量操作的时候,都会使用forEach来实现。如果是一个LIst集合的参数的话,要想在xml中访问,并且没有设置@param的情况下,需要使用 list来访问。
9.6.1 批量添加
首先,添加的返回值类型要么是添加了几条数据,要么是void。我们就使用void即可,然后内容因为是批量添加,一条也好,多条也好,使用List集合来作为属性。
List 使用@Param 来指明属性的名称
Interface
void insertMoreEmp(@Param(“empList”) List empList);
xml

insert into table_emp(emp_id, emp_name, age, gender) values

(null, #{emp.empName}, #{emp.age}, #{emp.gender})

foreach,collection表示从那个集合属性里面遍历,也就是我们的 empList,然后item是单个遍历出来的对象,separator是分隔符,每一次循环和每一次循环之间用 , 分割。
9.6.2 批量删除
其实和批量增加是一样的,会了就会。
Interface
void deleteMoreEmp(@Param(“empArray”) Integer[] empId);
xml

delete from table_emp where emp_id in (

#{empId}

)

Test
@Test
public void test3() {

Integer[] integers = new Integer[15];for (int i = 8; i <= 22; i++) {integers[i-8] = i;
}SqlSession sqlSession = DataSourceUtils.getSqlSession();assert sqlSession != null;
DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class);mapper.deleteMoreEmp(integers);

}

9.7 sql, include标签
可以用来记录一段sql, 在使用的地方使用 include标签来引入

  1. Mybatis的缓存
    和浏览器中的缓存相同,把一些没有变动过的东西缓存到本地,在下次查询的时候,如果没有增删改操作,则直接从缓存内取出数据,不会在去重新查询数据库。
    10.1 Mybatis的一级缓存
    Mybatis的一级缓存是默认开启的,就算仅仅搭建了一个mybatis框架。什么都没有做,那他也是默认开启的。可以直接使用的。一级缓存是Session级别的,在同一个Session中,查询的数据会被缓存,下一次查询,不会在去访问数据库,从缓存中取出。

使一级缓存失效的四种情况:
不同的SqlSession对应不同的一级缓存
同一个SqlSession但是查询条件不同
同一个SqlSession查询期间执行了任意一个增删改操作
同一个SqlSession两次查询期间执行了手动清除缓存操作

10.2 Mybatis的二级缓存
二级缓存是SqlSessionFactory级别的,一级缓存是SqlSession级别的。同一个SqlSessionFactory创建出来的SqlSession查询结果会被缓存,若在此后再次执行相同的查询操作,结果就会从缓存中取出

二级缓存开启的条件
在核心配置文件中,设置全局配置属性cacheEnabled=“true”。默认为true。不需要设置。
在映射文件,也就是Mapper.xml中,设置标签 也就是如下:

<?xml version="1.0" encoding="UTF-8" ?>

<cache />

二级缓存必须在SqlSession关闭或提交后才有效 查询的数据所转换的实体类型必须实现序列化的接口

使二级缓存失效的情况
两次查询之间执行了任意的增删改,都会使一级缓存和二级缓存一起失效。

  1. Mybatis逆向工程
    pom.xml

<?xml version="1.0" encoding="UTF-8"?>

4.0.0

<groupId>org.example</groupId>
<artifactId>mybatis_mbg</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target>
</properties><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version></dependency>
</dependencies><!-- 控制maven在构建过程的相关配置 -->
<build><!-- 构建过程用到的插件--><plugins><!-- 具体地插件,逆向工程是以插件的形式存在--><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依赖 --><dependencies><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency></dependencies></plugin></plugins>
</build>

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>

  1. Mybatis分页插件
    limit index, pageSize

pageSize: 每页显示的条数
pageNum: 当前页的码页
index: 当前页起始索引,公式为: (pageNum-1)*pageSize
count: 总记录数
totalPage: 总页数, totalPage = count / pageSize
if (count % pageSize != 0) {
totalPage += 1;
}

12.1 使用步骤
添加Pom依赖

com.github.pagehelper
pagehelper
5.1.2

配置插件
在mybatis-config.xml中有一个plugins,在内配置

然后就可以直接使用了,新建Test类,需要借助PageHelper.startPage来完成。
@Test
public void test1() throws IOException {

EmpMapper mapper = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession().getMapper(EmpMapper.class);// 在查询之前开启分页功能
PageHelper.startPage(1, 4);List<Emp> list = mapper.selectByExample(null);list.forEach(System.out::println);

}

12.2 通过分页插件获取相关数据
PageHelper.startPage(1, 4); 可以获取一个Page对象
Page objects = PageHelper.startPage(1, 4);
输出这个Page对象就会发现里面包含了需要使用到的信息。
Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=7, pages=2, reasonable=false, pageSizeZero=false}
但是有时候这些信息并不够使用,所以可以使用PageInfo对象,list是查询出来的结果。要对list进行分页
PageInfo pageInfo = new PageInfo<>(list);

System.out.println(pageInfo);
得到如下结果。
PageInfo{pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=7,
pages=2, list=Page{count=true, pageNum=1, pageSize=4, startRow=0,
endRow=4, total=7, pages=2, reasonable=false, pageSizeZero=false},
prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false,
hasNextPage=true, navigatePages=8, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}

Mybatis3快速上手(详细)相关推荐

  1. 【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 | 新发出品 | 良心教程)

    文章目录 一.前言 二.插件下载 三.案例1:第三人称自由视角,Free Look character场景 1.场景演示 2.组件参数 2.1.CinemachineBrain:核心 2.2.Cine ...

  2. 【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 新发出品 良心教程)

    文章目录 一.前言 二.插件下载 三.案例1:第三人称自由视角,Free Look character场景 1.场景演示 2.组件参数 2.1.CinemachineBrain:核心 2.2.Cine ...

  3. Cloud Computing:基于无影云电脑利用Python语言实现绘制“可爱小老虎”虎年快乐及无影云电脑简介、应用场景、使用体验(五步快速上手)分享图文教程之详细攻略

    Cloud Computing:基于无影云电脑利用Python语言实现绘制"可爱小老虎"虎年快乐及无影云电脑简介.应用场景.使用体验(五步快速上手)分享图文教程之详细攻略 目录 无 ...

  4. 基于 Vuepress 搭建个人博客,文章详细,助你快速上手

    搭建博客 几年前在小白阶段使用过 WordPress + 阿里云服务器 搭建了自己的博客,也走了很多坑,从零摸坑最后也弄好了,也顺便使用了阿里云的一些服务.但当时没有记录笔记的习惯,过了好久很多操作也 ...

  5. 【快速上手mac必备】常用优质mac软件推荐(音视频、办公、软件开发、辅助工具、系统管理、云存储)

    本文章的主要内容是我作为一名大四学生.准程序员.up主这三种身份来给大家推荐一下 mac 上好用的软件以及工具.本人也是从去年9月份开始从windows阵营转移到了mac阵营,刚开始使用的时候,也曾主 ...

  6. 快速上手RaphaelJS-Instant RaphaelJS Starter翻译(一)

    (目前发现一些文章被盗用的情况,我们将在每篇文章前面添加原文地址,本文源地址:http://www.cnblogs.com/idealer3d/p/Instant_RaphaelJS_Starter. ...

  7. yolo python_YOLO目标检测快速上手

    介绍 YOLO是基于深度学习端到端的实时目标检测系统,YOLO将目标区域预测和目标类别预测整合于单个神经网络模型中,实现在准确率较高的情况下快速目标检测与识别,更加适合现场应用环境.本案例,我们快速实 ...

  8. smarty半小时快速上手入门教程

    本文讲述了smarty快速上手入门的方法,可以让读者在半小时内快速掌握smarty的用法.分享给大家供大家参考.具体实现方法如下: 一.smarty的程序设计部分: 在smarty的模板设计部分我简单 ...

  9. 快速上手RaphaelJS--RaphaelJS_Starter翻译(一)

    Raphael Javascript是一个 Javascript的矢量库. 它可以处理SVG.VML格式的矢量图,它使用SVG W3C推荐标准和VML作为创建图形的基础,你可以用Javascript ...

最新文章

  1. Relay外部库使用
  2. 3D相机D2C对齐的方法
  3. java 代理的三种实现方式
  4. python软件怎么使用-Python快速入门—如何选择使用包管理工具?
  5. 计算机组成原理课后习题答案一
  6. Cutting Bamboos(牛客多校第九场H主席树+二分+思维)
  7. 2020牛客国庆集训派对day4 Emergency Evacuation
  8. c语言数字黑洞123问题,PAT-B 1019 数字黑洞 (C语言)
  9. 三星Note 10最新渲染图曝光:与之前爆料基本一致
  10. LeetCode 5367. 最长快乐前缀
  11. Java - package和import
  12. 张一鸣的心里“住着小马哥”
  13. Nginx 凭啥并发数可以达到 3w?
  14. 弹性分布式数据集RDD
  15. 自动控制原理8.3---相平面法
  16. Acer 4750G 安装ubuntu18.04的过程记录
  17. 中小企业信息网络安全解决方案
  18. windows服务创建工具srvany.exe介绍
  19. 无线通信算法工程师知识地图
  20. provisional headers are shown解决办法

热门文章

  1. error: 'ff_get_buffer' was not declared in this scope
  2. 中录国际 php,第四届公共卫生与预防医学国际学术会议(PHPM 2021)
  3. 指针 c语言 f(x amp n),C语言第8章 指针习题1(含答案)
  4. springboot+rabbitMq整合开发实战一
  5. php源码克隆,SiteCloner站点复制克隆PHP源码下载
  6. python使用谷歌翻译
  7. python两个时间内的工作日_python计算一段时间内的工作日(除周末、除中国节假日、加调休)和所有日期...
  8. javascript的递归函数
  9. 一个优秀的公众号运营者需要具备哪些能力?
  10. css表格文字超数量就竖排_CSS文字竖排 DIV CSS文字垂直竖列排版显示如何实现?...