目录
(2.3)快速开始_Spring + Mybatis + MP。
(2.4)快速开始_SpringBoot + Mybatis + MP。
(2.5.1)mybatis 和 mybatisplus的整合。
(2.5.2)ssm+mp整合之后,可以直接通过调用接口方法查询数据库,前提是代理模式(即有对应接口)。
(2.5.3)springboot + mybatis + mybatisplus。

对于Mybatis整合MP有常常有三种用法,分别是Mybatis+MP、Spring+Mybatis+MP、Spring Boot+Mybatis+MP。
(2.1.1)创建数据库以及表。
1.创建数据库mp,字符集选utf-8。
2.创建表、插入数据。
- -- 创建测试表
- CREATE TABLE `tb_user` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
- `user_name` varchar(20) NOT NULL COMMENT '用户名',
- `password` varchar(20) NOT NULL COMMENT '密码',
- `name` varchar(30) DEFAULT NULL COMMENT '姓名',
- `age` int(11) DEFAULT NULL COMMENT '年龄',
- `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- -- 插入测试数据
- INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
- ('1', 'zhangsan', '123456', '张三', '18', 'test1@itcast.cn');
- INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
- ('2', 'lisi', '123456', '李四', '20', 'test2@itcast.cn');
- INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
- ('3', 'wangwu', '123456', '王五', '28', 'test3@itcast.cn');
- INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
- ('4', 'zhaoliu', '123456', '赵六', '21', 'test4@itcast.cn');
- INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
- ('5', 'sunqi', '123456', '孙七', '24', 'test5@itcast.cn');
(2.1.2)创建工程。
1.创建一个maven工程。
2.导入依赖。
- "1.0" encoding="UTF-8"?>
- <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>
- <groupId>org.examplegroupId>
- <artifactId>Mybatis_PlusartifactId>
- <packaging>pompackaging>
- <version>1.0-SNAPSHOTversion>
- <modules>
- <module>Mybatis_and_MPmodule>
- modules>
- <properties>
- <maven.compiler.source>15maven.compiler.source>
- <maven.compiler.target>15maven.compiler.target>
- properties>
- <dependencies>
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plusartifactId>
- <version>3.5.3.1version>
- dependency>
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>8.0.27version>
- dependency>
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- <version>1.2.8version>
- dependency>
-
- <dependency>
-
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <optional>trueoptional>
- <version>1.18.26version>
- dependency>
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- <scope>testscope>
- dependency>
- <dependency>
-
- <groupId>org.slf4jgroupId>
- <artifactId>slf4j-log4j12artifactId>
- <version>1.7.7version>
- dependency>
- dependencies>
- <build>
- <plugins>
- <plugin>
-
- <groupId>org.apache.maven.pluginsgroupId>
- <artifactId>maven-compiler-pluginartifactId>
- <configuration>
- <source>1.8source>
- <target>1.8target>
- configuration>
- plugin>
- plugins>
- build>
- project>
注意事项有3个:
1、要加入spring的依赖,不然报错(我使用mybatis-plus的时候需要依赖spring的类)。
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.2.20.RELEASEversion>
- dependency>
2、mybatis核心加载mapper.xml映射文件或接口(即不需要映射文件)都行。
注意:下面的选一个就行(要么加载映射文件,要么加载接口)
3、解决了驼峰命名问题。
数据表是user_name,而查询写的是userName, 然后也查询成功了。
实体User中属性userName采用驼峰,对应数据库中的字段会是user_name

- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- " >
-
-
- <context:property-placeholder location="classpath:database.properties">context:property-placeholder>
-
-
- <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${driver}">property>
- <property name="url" value="${url}">property>
- <property name="username" value="${user}">property>
- <property name="password" value="${pwd}">property>
- bean>
-
- <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource">property>
-
- <property name="configLocation" value="classpath:mybatis.xml">property>
-
- <property name="mapperLocations" value="classpath:mapper/*.xml">property>
- bean>
-
-
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.anshangshi.mapper">property>
- bean>
-
-
- <context:component-scan base-package="com.anshangshi">context:component-scan>
-
-
- <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
- <property name="dataSource" ref="dataSource">property>
- bean>
-
-
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <tx:attributes>
- <tx:method name="add*" propagation="REQUIRED"/>
- <tx:method name="update*" propagation="REQUIRED"/>
- <tx:method name="del*" propagation="REQUIRED"/>
- <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
- tx:attributes>
- tx:advice>
-
- <aop:config>
- <aop:pointcut id="servicePointcut" expression="execution(* com.anshangshi.service..*.*(..))"/>
- <aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut">aop:advisor>
- aop:config>
-
- beans>

注意事项3个:
1、这个注解要这样写:@SpringBootTest(classes = MyApplication.class)
- @RunWith(SpringJUnit4ClassRunner.class)
- @SpringBootTest(classes = MyApplication.class)
- public class testMybatisSpringBoot {
- @Autowired
- private UserMapper userMapper;
- @Test
- public void test(){
- List
userList = userMapper.selectList(null); - for (User user : userList) {
- System.out.println(user);
- }
- }
- }
2、这个坐标的版本我改成3.4.3.1才能成功使用。(其他版本的不知道,3.1.1版本出现错误)
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-boot-starterartifactId>
- <version>3.4.3.1version>
- dependency>
3、修改java编译器的jdk版本,或者,在pom.xml中,使用的jdk版本为12才行(比如使用15版本的,提示不支持)。
注意:
- <properties>
- <maven.compiler.source>12maven.compiler.source>
- <maven.compiler.target>12maven.compiler.target>
- properties>

下面三种整合方式:接口方法都可以使用注解实现sql语句。
(必须代理模式下:即映射文件方法有对应接口方法)
- "1.0" encoding="UTF-8" ?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="mp.mapper.UserMapper">
- <select id="findById" resultType="User">
- select * from tb_user where id = #{id}
- select>
- mapper>
- public interface UserMapper extends BaseMapper
{ - User findById(Long id);
- }
其实跟原本差不多的用法:
- // 创建 MyBatis SqlSessionFactory
- InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- // 获取 UserMapper 接口的代理对象
- SqlSession session = sqlSessionFactory.openSession();
- UserMapper mapper = session.getMapper(UserMapper.class);
- ...............
为什么不能直接用接口调用方法?
因为那样没人帮你执行sql语句,因为mybatis不知道(你没告诉它) 。
- @Autowired
- private UserMapper userMapper;
-
- @Test
- public void testFindAll() {
- List
userList = userMapper.findAll(); - for (User user : userList) {
- System.out.println(user);
- }
- }
为什么可以直接用接口调用方法?
因为你整合ssm+mp时已经告诉mybatis或mybatisplus了。
映射xml文件+mp配置指定映射文件+接口(对应映射文件的抽象方法):(映射文件+接口=即代理模式)。
- #指定全局的配置文件
- #mybatis-plus.config-location=classpath:mybatis-config.xml
- #指定Mapper.xml文件的路径
- #mybatis-plus.mapper-locations=classpath*:mybatis/*.xml
为什么可以直接用接口调用方法?
因为mybatisplus帮你执行sql语句。
- @Test
- //插入方法
- public void test1(){
- User user = new User();
- user.setMail("1@itcast.cn");
- user.setAge(31);
- user.setUserName("caocao1");
- user.setName("曹操1");
- user.setPassword("123456");
- user.setAddress("北京");
- int result = userMapper.insert(user);
- System.out.println("数据库受影响的行数:"+result);
- //获取自增长后的id值,自增长后的id值会回填到user对象中
- System.out.println("id => "+user.getId());
- }

- @Test
- public void testUpdateById(){
- User user = new User();
- user.setId(1L);//条件,根据id更新
- user.setAge(19);//更新的字段
- user.setPassword("666");
- int result = userMapper.updateById(user);
- System.out.println("result => "+result);
- }
- @Test
- public void testUpdate(){
- User user = new User();
- user.setAge(20);//更新的字段
- user.setPassword("8888");
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("user_name","zhangsan");//匹配user_name = zhangsan 的用户数据
- //根据条件做更新
- int result = userMapper.update(user, wrapper);
- System.out.println("result => "+result);
- }
- @Test
- public void testUpdate2(){
- UpdateWrapper
wrapper = new UpdateWrapper<>(); - wrapper.set("age",21).set("password","999999")//更新的字段
- .eq("user_name","zhangsan");//更新的条件
- //根据条件做更新
- int result = userMapper.update(null, wrapper);
- System.out.println("result => "+result);
- }

- @Test
- public void testDeleteById(){
- //根据id删除数据
- int result = userMapper.deleteById(9L);
- System.out.println("result => "+result);
- }
- @Test
- public void testDeleteByMap(){
- Map
map = new HashMap<>(); - map.put("user_name","zhangsan");
- map.put("password","999999");
- //根据map删除数据,多条件之间是and关系
- int result = userMapper.deleteByMap(map);
- System.out.println("result => "+result);
- }
- @Test
- public void testDelete(){
- //用法一:
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("user_name","caocao1")
- .eq("password","123456");
- //用法二:
- User user = new User();
- user.setPassword("123456");
- user.setUserName("caocao");
- QueryWrapper
wrapper1 = new QueryWrapper<>(user); - //根据包装条件做删除
- //int result = userMapper.delete(wrapper);
- int result = userMapper.delete(wrapper1);
- System.out.println("result => "+result);
- }
- @Test
- public void testDeleteBatchIds(){
- //根据id批量删除数据
- int result = userMapper.deleteBatchIds(Arrays.asList(10L, 11L));
- System.out.println("result => "+result);
- }

注意: PaginationInnerInterceptor这种方式已经过时了。在 Mybatis-Plus 3.4.0 版本以后,推荐使用 MybatisPlusInterceptor 替代 PaginationInnerInterceptor。
MybatisPlusInterceptor 是一个更加通用、更加灵活的插件拦截器,可以实现多种拦截器的功能,例如分页、乐观锁、动态表名等。
- @Configuration
- @MapperScan("mp.mapper") //设置mapper接口的扫描包
- public class MybatisPlusConfig {
- /*@Bean //配置分页插件
- public PaginationInnerInterceptor paginationInnerInterceptor(){
- return new PaginationInnerInterceptor();
- }*/
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor() {
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
- return interceptor;
- }
- }
- @Test
- public void testSelectById(){
- User user = userMapper.selectById(1L);
- System.out.println(user);
- }
- @Test
- public void testSelectBatchIds() {
- //根据id批量查询数据
- List
userList = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L, 4L, 5L)); - for (User user : userList) {
- System.out.println(user);
- }
- }
- @Test
- public void testSelectOne() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - //查询条件(没有查到数据,则返回为null),查询的数据超过一条时,会抛出异常
- wrapper.eq("user_name","lisi1");
- //wrapper.eq("password","123456");//如果查询到多条数据,则报错
- User user = userMapper.selectOne(wrapper);
- System.out.println(user);
- }
- @Test
- public void testSelectCount() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.gt("age",20);//年龄大于20岁的用户
- //根据条件查询数据条数
- Integer count = userMapper.selectCount(wrapper);
- System.out.println("count => "+count);
- }
- @Test
- public void testSelectList() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - //设置查询条件
- wrapper.like("email","itcast");
- List
userList = userMapper.selectList(wrapper); - for (User user : userList) {
- System.out.println(user);
- }
- }
- @Test
- //测试分页查询
- public void testSelectPage() {
- Page
page = new Page<>(1,1);//查询第一页,查询一条数据 - //有参构造相当于设置了下面的这两个属性值
- /*page.setCurrent(1);
- page.setSize(1);*/
- QueryWrapper
wrapper = new QueryWrapper<>(); - //设置查询条件
- wrapper.like("email","itcast");
- IPage
iPage = userMapper.selectPage(page, wrapper); - System.out.println("数据总条数:"+iPage.getTotal());
- System.out.println("数据总页数:"+iPage.getPages());
- System.out.println("当前页数:"+iPage.getCurrent());
- List
records = iPage.getRecords();//获取查询的数据(其实是分页之后的数据,即第几页开始,有几条,例如这里:第1页,查询1条数据,所以这里只有1条数据) - //只有1条数据(满足条件的不止1条,但是只有分页之后的数据)
- //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (email LIKE ?) LIMIT ?
- for (User record : records) {
- System.out.println(record);
- }
- }




在 Java 中,$ 符号后面跟着的数字或字符串可以指代一个内部类或内部接口。$ 后面的内部类不仅在 Java 中适用,在 Mybatis-Plus 中同样也适用。
在实际使用中,内部类的命名规范一般是在外部类的类名后面添加 $ 符号和内部类名称。这样做的好处是,可以很容易地区分内部类和普通类,同时也方便了代码的组织和维护。
例如
com.example.OuterClass$InnerClass就表示OuterClass的一个名为InnerClass的内部类。

在 Mybatis-Plus 中,entity 表示实体类对象(Entity Object)。Entity Object 是指一个普通的 Java 类,用于描述数据库中的一条记录。
注意:如果我们既使用了实体类属性,又使用了 QueryWrapper 的一些 API 方法(例如 like()、eq() 等),那么这两种方式生成的 WHERE 条件是互相独立的,不会相互影响。
api生成的where条件:
QueryWrapper
wrapper = new QueryWrapper<>(); wrapper.gt("age", 18);
entity生成的where条件:
User user = new User();
user.setAge(18);
QueryWrapper
wrapper = new QueryWrapper<>(user);

- @Test
- public void testAllEq() {
- HashMap
params = new HashMap<>(); - params.put("name", "李四");
- params.put("age", "20");
- params.put("password", null);
- QueryWrapper
wrapper = new QueryWrapper<>(); - //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (password IS NULL AND name = ? AND age = ?)
- //wrapper.allEq(params);
-
- //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name = ? AND age = ?)
- //wrapper.allEq(params,false);
-
- //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name = ? AND age = ?)
- wrapper.allEq((k,v) -> (k.equals("age") || k.equals("id") || k.equals("name")),params);
- List
userList = userMapper.selectList(wrapper); - for (User user : userList) {
- System.out.println(user);
- }


- @Test
- public void testLike() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.likeLeft("name","五");
- //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name LIKE ?)
- //参数:%五(String)
- List
users = userMapper.selectList(wrapper); - for (User user : users) {
- System.out.println(user);
- }
- }

- @Test
- public void testOrderByAgeDesc() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - //按照年龄倒叙排序
- wrapper.orderByDesc("age");
- //SELECT id,user_name,name,age,email AS mail FROM tb_user ORDER BY age DESC
- //参数:无
- List
users = userMapper.selectList(wrapper); - for (User user : users) {
- System.out.println(user);
- }
- }

- @Test
- public void testOr() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("name","王五").or().eq("age",21);
- //SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name = ? OR age = ?)
- //参数:王五(String), 21(Integer)
- List
users = userMapper.selectList(wrapper); - for (User user : users) {
- System.out.println(user);
- }
- }

- @Test
- public void testSelect() {
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("name","王五")
- .or()
- .eq("age",21)
- .select("id","name","age");//指定查询字段
- //SELECT id,name,age FROM tb_user WHERE (name = ? OR age = ?)
- //参数:王五(String), 21(Integer)
- List
users = userMapper.selectList(wrapper); - for (User user : users) {
- System.out.println(user);
- }
- }

MyBatis-Plus 忽略修改字段的规则是通过在执行数据库更新操作时对实体对象进行解析和比较来确定的。具体规则如下:
当使用实体类对象进行数据修改时,MyBatis-Plus 会解析实体对象中的每个字段,检查其是否有值。
如果某个字段有值,则将该字段包含在更新语句中。
如果某个字段没有值,则根据字段类型的默认值规则来确定是否忽略该字段的更新操作:
- 对于整型(Integer、Long 等)和浮点型(Float、Double 等)字段,默认值为 0;
- 对于布尔型(Boolean)字段,默认值为 false;
- 对于字符串类型(String)字段,默认值为 null;
- 对于日期类型(Date、LocalDateTime 等)字段,默认值为 null。
根据以上规则,在执行数据修改时,如果某个字段没有值(即为默认值),则会被忽略不参与更新操作。
1.java中String类型可以存入mysql表的int类型。
2.mysql表的varchar类型可以存入java的int类型。
3.java的字符串可以存入mysql表的time类型。
4.mysql表的varchar类型可以存入java的LocalTime类型。
当然,前提是这些数据是符合格式的,比如20:20:20这种格式的字符串自然是可以存入mysql表的time类型的,如果是202020这种肯定是不行的。
所以java和mysql的字段类型不需要完全对应,只要符合格式就行。