配置
注解配置
1、@TableName(value=””)
mybatisplus会默认使用实体类的类名到数据中找对应的表,将bean中的映射表与value指的sql表对应
@TableName(value = "tbl_employee")public class Employee {}
2、@TableId(value = “”,type = )
主键策略,value指定表中的主键列的列名,如果实体属性名与列名一致,可以省略不指定;type指定主键策略;
//IdType.AUTO:自动生成
@TableId(value = "id",type = IdType.AUTO)
private Integer id ;
3、@TableField(value = “”)
将驼峰命名与数据库中下划线命名对应
@TableField(value = "last_name")
private String lastName;
4、@TableField(exist = )
字段是数据表中没有的,如果强行加入会报错,使用注解可以忽略它
@TableField(exist = false)
private Double salary;
全局配置
注解配置只能针对单个表或属性,若要所有表都遵循规定则要使用applicationContext.xml配置文件
<!--定义mybatis plus全局配置策略-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!--在2.3以后,dbColumnUnderline默认为true,自动开启,类似注解3-->
<property name="dbColumnUnderline" value="true"></property>
<!--全局的主键策略,注解只能用于一个,作用类似注解2-->
<property name="idType" value="0"></property>
<!--全局的表前缀策略配置,类似注解1-->
<property name="tablePrefix" value="tbl_"></property>
</bean>
通用操作
插入
- insert
@Test
public void testCommonInsert(){
//初始化Employee对象
Employee employee = new Employee();
employee.setLastName("mp");
employee.setEmail("111@guigu.com");
employee.setAge(23);
employee.setGender(2);
//插入到数据库,会根据实体类的每个属性进行非空判断,只有非空的属性对应的字段才会出现在sql语句中
Integer result = employeeMapper.insert(employee);
System.out.println("result:"+result);
//自动获取当前插入数据的ID
Integer id = employee.getId();
System.out.println(id);
}
- insertAllColumn
@Test
public void testCommonInsert(){
//初始化Employee对象
Employee employee = new Employee();
employee.setLastName("mp");
employee.setEmail("111@guigu.com");
employee.setAge(23);
employee.setGender(2);
//插入全部属性,不管属性是否非空,属性所对应的字段都会出现sql语句中
Integer result1 = employeeMapper.insertAllColumn(employee);
System.out.println("result1"+result1);
//自动获取当前插入数据的ID
Integer id = employee.getId();
System.out.println(id);
}
删除
- deleteById(根据ID删除)
@Test
public void testCommonDelect(){
//根据id删除
Integer integer = employeeMapper.deleteById(3);
System.out.println(integer);
}
- deleteByMap(根据条件删除)
@Test
public void testCommonDelect(){
//2.根据条件进行删除
//注意:put中的key写的是sql列名而不是属性名
Map<String,Object> columnmMap = new HashMap<>();
columnmMap.put("last_name","mp");
columnmMap.put("email","111@guigu.com");
Integer result = employeeMapper.deleteByMap(columnmMap);
System.out.println(result);
}
- deleteBatchIds(批量删除)
@Test
public void testCommonDelect(){
//3.批量删除
List<Integer> idlist = new ArrayList<>();
idlist.add(2);
idlist.add(3);
idlist.add(4);
Integer ids = employeeMapper.deleteBatchIds(idlist);
System.out.println(ids);
}
更新
- updateById
@Test
public void testCommonUpdate(){
//初始化修改对象
Employee employee = new Employee();
employee.setId(11);
employee.setLastName("草");
employee.setEmail("sdfsf@qq.com");
employee.setGender(0);
//和insert方法一样,会判断非空,如果是空就不会加入到sql语句中
Integer result = employeeMapper.updateById(employee);
System.out.println("result:"+result);
}
- updateAllColumnById
@Test
public void testCommonUpdate(){
//初始化修改对象
Employee employee = new Employee();
employee.setId(11);
employee.setLastName("草");
employee.setEmail("sdfsf@qq.com");
employee.setGender(0);
//和insertAllColumn一样不会判断非空,因此元素为空时就会被改为空
Integer result2 = employeeMapper.updateAllColumnById(employee);
System.out.println("result2:"+result2);
}
查询
- selectById(ID查询)
@Test
public void testCommonSelect(){
//通过ID查询
Employee employee = employeeMapper.selectById(7);
System.out.println(employee);
}
- selectOne(多列查询)
@Test
public void testCommonSelect(){
//2.通过多个列进行查询 例:id + lastName
//注意:selectOne只能得到一个结果,如果根据条件查询的有多个结果就会报错
Employee employee = new Employee();
employee.setId(7);
employee.setLastName("mp");
Employee employee1 = employeeMapper.selectOne(employee);
System.out.println(employee1);
}
- selectBatchIds(多ID查询)
@Test
public void testCommonSelect(){
//3.通过多个ID进行查询
List<Integer> idlist = new ArrayList<>();
idlist.add(10);
idlist.add(11);
List<Employee> employees = employeeMapper.selectBatchIds(idlist);
System.out.println(employees);
}
- selectByMap(map条件查询)
@Test
public void testCommonSelect(){
//4.通过map封装条件查询
//注意:put中的key写的是sql列名而不是属性名
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("last_name","tom");
columnMap.put("gender",1);
List<Employee> emps = employeeMapper.selectByMap(columnMap);
System.out.println(emps);
}
- selectPage(分页查询)
@Test
public void testCommonSelect(){
//5.分页查询,并不是物理分页
List<Employee> emps = employeeMapper.selectPage(new Page<>(2, 2), null);
System.out.println(emps);
}
条件构造器EntityWrapper
让用户自由的构建查询条件,实体包装器,主要用于处理sql拼接吗,排序,实体参数查询等。
注意:使用的数据库字段,不是java属性
- 带条件查询
/**
* 条件构造器 查询操作
*/
@Test
public void testEntityWrapperSelect(){
//分页查询表中年龄在18-50之间性别为i男性且姓名xx的所有用户
List<Employee> list = employeeMapper.selectPage(new Page<Employee>(1, 2), new EntityWrapper<Employee>()
.between("age", 18, 50)
.eq("gender", 1)
.eq("last_name", "Tom"));
System.out.println(list);
}
@Test
public void testEntityWrapperSelect(){
//查询表中性别为女,且名字带有“老师”或邮箱带有“a”
//or方法
List<Employee> emps = employeeMapper.selectList(new EntityWrapper<Employee>().eq("gender",1)
.like("last_name","老师")
.or()// SELECT id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE (gender = ? AND last_name LIKE ? OR email LIKE ?)
.like("email","a")
);
System.out.println(emps);
}
@Test
public void testEntityWrapperSelect(){
//查询表中性别为女,且名字带有“老师”或邮箱带有“a”
//ornew方法
List<Employee> emps = employeeMapper.selectList(new EntityWrapper<Employee>().eq("gender",1)
.like("last_name","老师")
.orNew()//SELECT id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE (gender = ? AND last_name LIKE ?) OR (email LIKE ?)
.like("email","a")
);
System.out.println(emps);
}
@Test
public void testEntityWrapperSelect(){
//查询性别为女,根据age进行排序(asc/desc),简单分页
List<Employee> emps = employeeMapper.selectList(new EntityWrapper<Employee>()
.eq("gender",0)
.orderBy("age")//以字段age排正序
//.orderDesc(Arrays.asList(new String[]{"age"}))//倒序,传入的为集合
//.orderAsc(Arrays.asList(new String[]{"age"}))//正序,传入的为集合
.last("desc limit 1,3")//之接将指接到sql语句后;倒序,显示第一条到第三条数据
);
System.out.println(emps);
}
- 带条件的修改操作
/**
* 条件构造器 修改操作
*/
@Test
public void testEntityWrapperUpdate(){
//将名字为Tom年龄为22的修改名字、邮箱和性别
Employee employee = new Employee();
employee.setLastName("产老师");
employee.setEmail("cls@qq.com");
employee.setGender(0);
Integer update = employeeMapper.update(employee,new EntityWrapper<Employee>()
.eq("last_name","Tom")
.eq("age",22));
System.out.println(update);
}
- 带条件删除
/**
* 条件构造器 删除操作
*/
@Test
public void testEntityWrapperDelete(){
//将名字为Tom,年龄为22的删除
Integer delete = employeeMapper.delete(new EntityWrapper<Employee>()
.eq("last_name","Tom")
.eq("age",22));
System.out.println(delete);
}
条件构造器Condition
内部还是wrapper
@Test
public void testEntityWrapperSelect(){
//分页查询表中年龄在18-50之间性别为i男性且姓名xx的所有用户
//condition使用了单例模式,所以直接调用。create方法,之后的使用和wrapper相同
List emps = employeeMapper.selectPage(new Page<Employee>(1, 2),
Condition.create()
.between("age", 18, 50)
.eq("gender", "1")
.eq("last_name", "Tom"));
}
ActiveRecord(活动记录)
一种领域模型模式,特点是一个模型类对应关系数据库中的一个表,而模型类的一个实例对应表中的一行记录。
动态语言使用广泛
使用AR模式
让实体类继承Model类并且实现主键指定方法
public class Employee extends Model<Employee> {
/**
* 返回主键
* @return
*/
@Override
protected Serializable pkVal() {
return id;
}
- 通用插入
/**
* AR 插入操作
*/
@Test
public void testARInsert(){
Employee employee = new Employee();
employee.setLastName("宋老师");
employee.setGender(0);
employee.setAge(23);
employee.setEmail("song@qq.com");
boolean insert = employee.insert();
System.out.println(insert);
}
- 通用更新
/**
* AR 更新操作
*/
@Test
public void testARUpdate(){
Employee employee = new Employee();
employee.setEmail("qwe@qq.com");
employee.setId(16);
boolean result = employee.updateById();
System.out.println(result);
}
- 通用查询
根据ID查询
/**
* AR 查询操作
*/
@Test
public void testARSelect(){
Employee employee = new Employee();
//方式1
Employee employee1 = employee.selectById(16);
//方式2
employee.setId(1);
Employee employee2 = employee.selectById();
System.out.println("employee1:"+employee1+"employee2:"+employee2);
}
查询全部
@Test
public void testARSelect(){
Employee employee = new Employee();
List<Employee> employees = employee.selectAll();
System.out.println(employees);
}
条件查询
@Test
public void testARSelect(){
Employee employee = new Employee();
List<Employee> employees = employee.selectList(new EntityWrapper<Employee>().like("last_name", "老师"));
System.out.println(employees);
}
统计查询(统计符合要求的数据有多少)
@Test
public void testARSelect(){
Employee employee = new Employee();
int gender = employee.selectCount(new EntityWrapper<Employee>().eq("gender", 0));
System.out.println(gender);
}
- 通用删除
/**
* AR 删除操作,删除不存在的逻辑上属于成功,因此返回true
*/
@Test
public void testARDelete(){
Employee employee = new Employee();
//方法一
boolean b = employee.deleteById(1);
//方法二
employee.setId(2);
boolean b1 = employee.deleteById();
System.out.println("b"+b+"b1"+b1);
}
条件删除
/**
* AR 删除操作,删除不存在的逻辑上属于成功,因此返回true
*/
@Test
public void testARDelete(){
Employee employee = new Employee();
boolean delete = employee.delete(new EntityWrapper().like("last_name", "xiao"));
System.out.println(delete);
}
- 分页操作
/**
* AR 分页复杂操作
*/
@Test
public void testARPage(){
Employee employee = new Employee();
Page<Employee> employeePage = employee.selectPage(new Page<Employee>(1, 1), new EntityWrapper<Employee>().like("last_name", "老"));
List<Employee> emps = employeePage.getRecords();//获取数据
System.out.println(emps);
}
代码生成器
可以自动生成service层,controller层,mapper,beans等
配置代码
在test中写入生成配置代码
package com.atguigu.mp.test;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
/**
* @description:
* @author: yuqiong
* @createDate: 2020/1/19
* @version: 1.0
*/
public class Testmp {
/**
* 代码生成
*/
@Test
public void genCode(){
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("testjava");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://39.96.44.244/readbook?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("useservice"); //模块名
pc.setParent("com.wenhua.readbook");
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("readbook_bookrack");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
插件扩展
分页插件
配置
方法一:在mybatis配置文件中配置
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin>
</plugins>
方法二:在application.xml中配置
<!--sqlSessionFactoryBean中配置-->
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!--插件注册-->
<property name="plugins">
<list>
<!--注册分页插件-->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
</list>
</property>
</bean>
测试
public class Testmp {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper",EmployeeMapper.class);
/**
* 测试分页插件,可以获取各种信息
*/
@Test
public void testPage(){
Page<Employee> employeePage = new Page<>(1,1);
List<Employee> employees = employeeMapper.selectPage(employeePage, null);
System.out.println(employees);
System.out.println("获取分页相关一些信息");
System.out.println("总条数"+employeePage.getTotal());
System.out.println("当前页面"+employeePage.getCurrent());
System.out.println("总页码"+employeePage.getPages());
System.out.println("每个页面的条件"+employeePage.getSize());
System.out.println("是否有上一页"+employeePage.hasPrevious());
System.out.println("是否有下一页"+employeePage.hasNext());
//将查询的结果封装到page对象中
employeePage.setRecords(employees);
}
}
}
执行分析插件
分析DELETE UPDATE语句,防止小白,或者恶意进行delete update全表操作
只建议在开发环境中使用,不建议在生产环境使用,mysql5.6.3以上
在插件底层通过sql语句分析命令:Explain分析当前sql语句,根据结果集中的Extra列来断定当前是否是全表操作
配置
<!--注册执行分析插件-->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<!--发现问题是否停止操作-->
<property name="stopProceed" value="true"></property>
</bean>
当出现全表操作时会报错,阻止全表操作
/**
* 测试sql执行分析操作
*/
@Test
public void testSQLExplain(){
employeeMapper.delete(null);
}
性能分析插件
用于输出每条sql语句及其执行时间,sql性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题。
<!--注册性能分析插件-->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<!--显示格式化后的sql语句-->
<property name="format" value="true"></property>
<!--执行事件,超过则暂停-->
<property name="maxTime" value="5"></property>
</bean>
乐观锁插件
如果想实现如下需求:当要更新一条记录的时候,希望这条记录没有被别人更新
实现原理:取出记录时,获取当前version;更新记录时,带上这个version;执行更新时,set version = yourVersion + 1 where version = yoursVersion;如果version不对,就更新失败
@Version用于注解实体字段,必须要有
<!--注册乐观锁插件-->
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor"></bean>
自定义全局操作
根据mybatisplus的autosqlinjector可以自定义各种sql,注入到全局中,相当于自定义mybatisplus自动注入的方法。
mybatis需要在xml中进行配置的sql语句,现在通过扩展autosqlinjector在加载mybatis环境时就注入
AutoSqlInjector
- 在mapper接口中定义相关的crud方法
- 扩展AutoSqlInjector inject方法,实现mapper接口中方法要注入的SQL
- 在MP全局策略中,配置自定义注入器
