概念
中文官方网站
补充文档
MP是MyBatis的增强工具,在MyBatis基础上只做增强不做改变,
最新版(Spring 加入依赖)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
MP的application.yml配置
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # mapper路径
type-enums-package: com.training.enums #枚举类型存放路径
configuration:
map-underscore-to-camel-case: true #指将带有下划线的表字段映射为驼峰格式的实体类属性
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler #默认枚举类型处理器
MP直接使用
xxxmapper接口相当于以前的xxxdao接口
xxxmapper接口需要继承BaseMapper<T>
,这里的范型T指的是对应的实体类,例如操作User实体类,这里就写User
public void testFindAll() throws Exception{
//mapper配置文件
String config ="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(config);
//注意下面这行builder与以前MyBatis时区别
//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//原MyBatis
SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);//MP
SqlSession sqlSession=sqlSessionFactory.oopenSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//测试
//List<User> users=userMapper.findAll();//原MyBatis,需要在mapper接口写具体方法,然后接口对应mapper.xml写方法对应sql语句
List<User> users=userMapper.selectList(null);//不用自己写mapper接口中的方法和对应mapper.xml中的sql语句,MP会自动生成
for(User user:users){
System.out.println(user);
}
//直接运行会报错,需要在User类上加注解@TableName("数据库对应表表名")
//默认会找表名为对象首字母小写的表,例如这里就会默认去找user表
}
@TableName("")//加上之后和数据库的表映射
public class User{
//省略
}
Spring+MyBatis+MP
可以省略 sqlSessionFactory、sqlSession 等步骤
实现步骤
1、编写jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mp? useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL =false
jdbc.username=root
jdbc.password=root
2、编写applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:*.properties"/>
<!-- 定义数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="maxActive" value="10"/>
<property name="minIdle" value="5"/>
</bean>
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--扫描mapper接口,使用的依然是Mybatis原生的扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.itcast.mp.simple.mapper"/>
</bean>
</beans>
3、编写User对象以及UserMapper接口
package cn.itcast.mp.simple.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
package cn.itcast.mp.simple.mapper;
import cn.itcast.mp.simple.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> {
}
4、测试程序
测试的时候,如果说找不到jdbc.properties,就是说test目录下没有,把他们从java目录下拷贝过去就行了。这里的测试类是在test目录下的,其他的文件是在java目录下的。
import cn.itcast.mp.simple.mapper.UserMapper;
import cn.itcast.mp.simple.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestSpringMP {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList(){
List<User> users = this.userMapper.selectList(null);
for (User user : users) {
} }
SpringBoot+MyBatis+MP
使用SpringBoot 将进一步简化MP的整合。
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--简化代码的工具包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus的springboot支持-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
log4j.properties:
log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
实现步骤
1、application.properties
spring.application.name = itcast-mp-springboot
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mp?
useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL
=false
spring.datasource.username=root
spring.datasource.password=root
2、实体类
package cn.itcast.mp.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
3、编写mapper
package cn.itcast.mp.mapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> {
}
4、编写启动类
package cn.itcast.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@MapperScan("cn.itcast.mp.mapper") //设置mapper接口的扫描包 @SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
} }
5、测试程序
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest //SpringBoot测试注解
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
List<User> userList = userMapper.selectList(null);
for (User user : userList) {
System.out.println(user);
}
}
}
注解
MP插件的id策略
在POJO类上指定id策略
package cn.itcast.mp.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
@TableId(type=IdType.AUTO)//设置id策略为自增长
private Long id;
private String userName;
@TableField(select=false)//查询的时候不返回此字段值
private String password;
private String name;
private Integer age;
@TableField(value = "email")//数据库中该字段名为email
private String mail;
@TableField(exist=false)//sql语句中忽略address
private String address;//数据库中不存在的
}
TableField
作用:
对象中的属性名和字段名不一致的问题(驼峰问题会自动处理)
对象中的属性字段在表中不存在的问题
对象中的属性字段不返回
自动填充问题,例如创建时间、修改时间等@TableField(fill = FieldFill.INSERT_UPDATE)
具体参考csdn相关文章
@Version
处理乐观锁
通用CRUD
直接参考官网
insert
插入后,会回填。例如id主键字段是数据库自增的,我们在对象user不设置。那么执行insert之后,MP会把id回填到user对象。
//插入语句
int result=this.userMapper.insert(user);//返回的result是受影响的记录数
update
根据id更新:
//user此user中有的属性字段将被更新,没有的字段不会被更新
int result=this.userMapper.updateById(user);//返回的result是受影响的记录数
根据条件更新
方式一
public void testUpdate(){
User user=new User();
user.setAge(19);
user.setPassword("666");
QueryWrapper<User> wrapper=new QueryWrapper<>();//QueryWrapper相当于条件
wrapper.eq("user_name","zhangsan")//第一个参数是数据库的字段名
//更新操作
int result=this.userMapper.update(user,wrapper);//返回值是受影响的数据条数
}
方式二
public void testUpdate(){
UpdateWrapper<User> wrapper =new UpdateWrapper<>();//UpdateWrapper更新字段,有set操作
wrapper.set("age",21).set("password","9999")//第一个参数还是数据库的字段名
//更新操作
int result=this.userMapper.update(user,wrapper);//返回值是受影响的数据条数
}
delete
根据id删除
int result=this.userMapper.deleteById(user.getId());//返回的result是受影响的记录数
根据columnMap条件删除
多条件之间是and关系
Map<String,Object> map=new HashMap<>();
map.put("User_name","zhangsan");//第一个参数是数据库字段名。
map.put("password","123456");
int result=this.userMapper.deleteByMap(map);
根据条件删除
public void testDelete(){
//方式一
//QueryWrapper<User> wrapper=new QueryWrapper<>();//QueryWrapper相当于条件
//wrapper.eq("user_name","zhangsan")//第一个参数是数据库的字段名
//方式二(推荐)
User user=new User();
user.setUserName("zhangsan");
user.setPassword("123456");
QueryWrapper<User> wrapper=new QueryWrapper<>(user);//直接把user作为条件包装
//删除操作
int result=this.userMapper.update(wrapper);//返回值是受影响的数据条数
}
根据Id批量删除
public void testDeleteBatchIds(){
int result=this.userMapper.deleteBatchIds(Arrays.asList(10,11));//删除id为10 或 11 的记录
}
select
根据Id查询
User user=this.userMapper.selectById(user.getId());
根据Id批量查询
public void testSelectBatchIds(){
List<User> users=this.userMapper.selectBatchIds(Arrays.asList(10,11));//查询id为10 或 11 的记录
}
查询一条数据selectOne
注:数据有多条,会报错,没有符合条件的数据会返回null
public void testSelectOne(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
//查询条件
wrapper.eq("user_name","zhangsan")//第一个参数是数据库字段名
this.userMapper.selectOne(wrapper);
}
查询条数selectCount
public void testSelectCount(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
//查询条件
wrapper.gt("age",20)//第一个参数是数据库字段名,age>20的记录
Integer count=this.userMapper.selectCount(wrapper);
}
查询数据列表selectList
public void testSelectList(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
//查询条件
wrapper.like("email","gmail")//第一个参数是数据库字段名,前后都加%
List<User> users=this.userMapper.selectList(wrapper);
}
分页查询selectPage
IPage接口用于封装查询出来的结果
需要配置类(可以直接写到springboot启动类同目录下)
@Configuratiion
public class MyBatisPlusConfig{
@Bean //配置分页插件
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
测试代码
public void testSelectpage(){
Page<User> page=new Page<>(1,1);//第一个参数是当前第几页,第二个参数是每页几条
QueryWrapper<User> wrapper=new QueryWrapper<>();
//查询条件
wrapper.like("email","gmail")//第一个参数是数据库字段名,前后都加%
IPage<User> iPage=this.userMapper.selectPage(page,wrapper);
System.out.println("数据总数:"+iPage.getTotal());
//拿数据
List<User> users=iPage.getRecords();
}
配置
在MP中有大量的配置,其中一部分是MyBatis原生的配置,另一部分是MP的配置
基本配置
configuration
MyBatis主配置文件位置,如果有单独的MyBatis配置,请将其路径配置到configuration中。
SpringBoot项目:配置在application.properties中
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # mapper路径
type-enums-package: com.training.enums #枚举类型存放路径
configuration:
map-underscore-to-camel-case: true #指将带有下划线的表字段映射为驼峰格式的实体类属性
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler #默认枚举类型处理器
SpringMVC项目
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
mapperLocations
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置。
SpringBoot项目:配置在application.properties中
#指定Mapper.xml文件的路径
mybatis-plus.mapper-locations = classpath:mybatis/*.xml
SpringMVC项目
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
</bean>
typeAliasesPackage
MyBatis别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)。
配置这个之后,mapper.xml文件中的resultType就不用写全路径名字了。
#指定实体对象扫描包
mybatis-plus.type-aliases-package = cn.itcast.mp.pojo
SpringMVC项目
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
</bean>
进阶配置
使用配置类
在MapperScan注解中写mapper接口的包路径,就不用在每个mapper接口上加@Mapper
注解
@Configuration
@EnableTransactionManagement
@MapperScan("com.training.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInnerInterceptor paginationInterceptor() {
return new PaginationInnerInterceptor();
}
}
条件构造器 Wrapper接口
常用方法
allEq
public void testAllEq(){
Map<String,Object> params=new HashMap<>();
params.put("name","zhangsan");
params.put("age",20);
params.put("password",null);
QueryWrapper<User> wrapper=new QueryWrapper<>();
//方式一
//wrapper.allEq(params)
//方式二
//wrapper.allEq(params,false);//false代表password is null是否作为条件
//方式三
wrapper.allEq((k,v)->(k.equals("age")||k.equals("id")),params);//当传入的查询条件的k匹配第一个参数的时候,传入的条件才作为sql查询条件。例如这里传入name、age、password,但是只有age匹配,所以只有age作为查询条件。
List<User> users = this.usetMapper.selectList(wrapper);
}
基本比较操作方法
eq 等于
ne 不等于
gt 大于
ge 大于等于
lt 小于
le 小于等于
between BETWEEN 值1 AND 值2
notBetween NOT BETWEEN 值1 AND 值2
in 字段 in (v1,v2,v3…)
notIn 字段 NOT IN (v1,v2,v3,…)
模糊查询
like
like(“name”,“zhangsan”) //前后都加%
notLike
notLike(“name”,“zhang”)//前后都加%
likeLeft
likeLeft(“name”,“zhang”)//左边加%
likeRight
likeRight(“name”,“zhang”)//右边加%
排序方法
orderByDesc
orderByDesc(“age”)// 按照年龄倒序排序
逻辑方法
or and
public void testOr(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name","zhangsan").or().eq("age",20);
List<User> users = this.usetMapper.selectList(wrapper);
}
select指定查询字段
public void testSelect(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name","zhangsan").or().eq("age",20).select("id","name","age");
List<User> users = this.usetMapper.selectList(wrapper);
}
逆向工程生成POJO
首先参考:
官方文档
不同MP版本对应代码不同,MP3.5.1版本之前参考官方文档。
示例
依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
逆向工程代码:
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mp?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false", "root", "12345678")
.globalConfig(builder -> {
builder.author("kramer") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("src/main/java"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("mp1") // 设置父包名
.moduleName("mp2") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "src/main/resources/mapper")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_enum") // 设置需要生成的表名
.addTablePrefix(""); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
MP自定义语句
将自定义语句用注解写在mapper接口类上,然后在service直接调用这个方法
@Select("SELECT course.* from original_course course left join config_course config on course.course_config_id=config.id where course.calendar_flag = 0 and config.calendar_create_flag=1 and lark_calendar_id=null limit 50")
List<OriginalCourse> courseList();