入门mybatis"/>
如何快速的入门mybatis
mybatis-plus
- 前言
- 一、spring整合mybatis-plus
- 1.配置
- mvn坐标
- spring核心配置文件
- 数据库信息(db.properties)
- 实体类
- mapper接口
- 2.使用
- 测试
- 查询
- 携带条件查询
- 删除
- 修改
- 插入
- Condition
- Model
- model测试
- 3.代码生成器
- 坐标
- 代码生成
- 3.注册插件
- 分页插件
- 执行分析插件
- 性能分析插件
- 乐观锁插件
- 4.自定义全局配置
- 使用
- 注意(驼峰下划线配置)
- 5.逻辑删除
- 改动
- 6.公共字段填充
- 步骤
- 二、springboot-mybatis-plus
前言
熟练使用mybatis 等orm框架,mybatis-plus是对mybatis的进一步拓展,
mybatis能够使用的,mybatis-plus也可以使用,而且可以提供了更加方便简洁的开发方式提高开发效率
一、spring整合mybatis-plus
1.配置
mvn坐标
在ssm环境下导入坐标<!-- mp依赖mybatisPlus 会自动的维护Mybatis 以及MyBatis-spring相关的依赖--><!--普通ssm只需导入该坐标--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>2.3</version></dependency>
spring核心配置文件
<!-- 数据源 --><context:property-placeholder location="classpath:db.properties"/><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 事务管理器 --><bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 基于注解的事务管理 --><tx:annotation-driven transaction-manager="dataSourceTransactionManager"/><!-- 配置SqlSessionFactoryBean Mybatis提供的: org.mybatis.spring.SqlSessionFactoryBeanMP提供的:com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean--><bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"><!-- 数据源 --><property name="dataSource" ref="dataSource"></property><property name="configLocation" value="classpath:mybatis-config.xml"></property><!-- 别名处理 --><property name="typeAliasesPackage" value="com.atguigu.mp.beans"></property> <!-- 注入全局MP策略配置 --><property name="globalConfig" ref="globalConfiguration"></property></bean><!-- 定义MybatisPlus的全局策略配置--><bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"><!-- 在2.3版本以后,dbColumnUnderline 默认值就是true --><property name="dbColumnUnderline" value="true"></property> <!--将下划线和字母大写设置--><!-- 全局的主键策略 --><property name="idType" value="0"></property><!-- 全局的表前缀策略配置 --><property name="tablePrefix" value="tbl_"></property></bean><!-- 配置mybatis 扫描mapper接口的路径--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.atguigu.mp.mapper"></property></bean>
数据库信息(db.properties)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mp_plus
jdbc.username=root
jdbc.password=123456
实体类
@TableName(value="empty")
public class Employee {/** @TableId:* value: 指定表中的主键列的列名, 如果实体属性名与列名一致,可以省略不指定. * type: 指定主键策略. */@TableId(value="id" , type =IdType.AUTO) //主键private Integer id ; // int @TableField(value = "last_name") //非主键private String lastName; private String email ;private Integer gender; private Integer age ;@TableField(exist=false) 表示数据库没有说该属性对于的字段private Double salary ; getter...setter...
}
mapper接口
/*** Mapper接口* * 基于Mybatis: 在Mapper接口中编写CRUD相关的方法 提供Mapper接口所对应的SQL映射文件 以及 方法对应的SQL语句. * * 基于MP: 让XxxMapper接口继承 BaseMapper接口即可.* BaseMapper<T> : 泛型指定的就是当前Mapper接口所操作的实体类类型 * */
public interface EmployeeMapper extends BaseMapper<Employee> {无需写sql映射文件,当然也可以添加映射文件// Integer insertEmployee(Employee employee );// <insert useGeneratedKeys="true" keyProperty="id" > SQL...</insert>
}
2.使用
测试
public class TestMP {private ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");private EmployeeMapper employeeMapper = ioc.getBean("employeeMapper",EmployeeMapper.class);
}
查询
List<Employee> employees = employeeMapper.selectList(null); 设置条件为nullSystem.out.println("查询全部"+employees);Employee employee = employeeMapper.selectById(2);System.out.println("查询单个"+employee);ArrayList<Integer> employees1 = new ArrayList<Integer>();employees1.add(1);employees1.add(2);List<Employee> employees2 = employeeMapper.selectBatchIds("批量查询"+employees1);employees2.forEach(user->{System.out.println(user);});Integer integer = employeeMapper.selectCount(null);设置条件为nullSystem.out.println("查询记录数"+integer);// new Page<Employee>(1, 2) 设置查看第一页,显示两条数据List<Employee> emps =employeeMapper.selectPage(new Page<Employee>(1, 2),null)条件为nullSystem.out.println("分页查询"+emps);// 通过多个列进行查询 id + lastName
// Employee employee = new Employee();
// //employee.setId(7);
// employee.setLastName("小泽老师");
// employee.setGender(0);
//
// Employee result = employeeMapper.selectOne(employee);// 通过Map封装条件查询
// Map<String,Object> columnMap = new HashMap<>();
// columnMap.put("last_name", "Tom");
// columnMap.put("gender", 1);
//
// List<Employee> emps = employeeMapper.selectByMap(columnMap); List<Employee> emps = employeeMapper.selectList(new EntityWrapper<Employee>().eq("gender", 0).like("last_name", "老师")//.or() // SQL: (gender = ? AND last_name LIKE ? OR email LIKE ?) .orNew() // SQL: (gender = ? AND last_name LIKE ?) OR (email LIKE ?) .like("email", "a"));List<Employee> emps = employeeMapper.selectList(new EntityWrapper<Employee>().eq("gender", 0).orderBy("age") 默认升序//.orderDesc(Arrays.asList(new String [] {"age"}))根据age降序.last("desc limit 1,3") //这种属于sql拼接,不安全);
携带条件查询
分页查询带条件List<Employee> emps =employeeMapper.selectPage(new Page<Employee>(1, 2),new EntityWrapper<Employee>().between("age", 18, 50) 注意:指定的是数据库字段表示类属性.eq("gender", 1).eq("last_name", "Tom") 他们都是and的关系);EntityWrapper是构造条件的类public class EntityWrapper<T> extends Wrapper<T>EntityWrapper继承了Wrapper 还有一个Condition也继承了 Wrapper<T>
删除
List<Employee> employees = employeeMapper.selectList(null);带条件
employeeMapper.delete(new EntityWrapper<Employee>().eq("last_name", "Tom").eq("age", 22));批量删除employeeMapper.deleteBatchIds(new ArrayList<>());删除的id employeeMapper.deleteById(1)
修改
Employee employee = new Employee();employee.setLastName("老师");employee.setEmail("cls@sina");employee.setGender(0);employeeMapper.update(employee,new EntityWrapper<Employee>().eq("last_name", "Tom").eq("age", 44));根据条件筛选数据进行修改不携带条件的方法,我们需要给他的实体类设置id才能够·有效的操作数据库数据
如 employee.setId(1);employeeMapper.updateById(employee);employeeMapper.updateAllColumnById(employee);
插入
Employee employee = new Employee();employee.setLastName("MP");employee.setEmail("mp@atguigu");//employee.setGender(1);//employee.setAge(22);employee.setSalary(20000.0);
//插入到数据库 // insert方法在插入时, 会根据实体类的每个属性进行非空判断,只有非空的属性对应的字段才会出现到SQL语句中Integer result = employeeMapper.insert(employee); //insertAllColumn方法在插入时, 不管属性是否非空, 属性所对应的字段都会出现到SQL语句中. Integer result = employeeMapper.insertAllColumn(employee);插入成功后,可以直接在该实体类里获取插入数据的id值
Condition
List<Employee > emps = employeeMapper.selectPage(new Page<Employee>(1,2),Condition.create().between("age", 18, 50).eq("gender", "1").eq("last_name", "Tom"));和EntityWrapper的使用是一样的,只不过创建的方式不一样Condition的是Condition.create()EntityWrapper是new但这只是低版本的,高版本的plus不支持EntityWrapper
参考gitee案例1
Model
实体类继承Model<T> ,当然mapper也好需要继承BaseMapper<Employee>
继承Model,还需要重写一个方法
protected Serializable pkVal() {return this.id;}此时的实体类就有许多的单表操作数据的方法了
model测试
public class TestMP {private ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");private EmployeeMapper employeeMapper = ioc.getBean("employeeMapper",EmployeeMapper.class);// AR 查询全部@Testpublic void select(){Employee employee=new Employee();List<Employee> employees = employee.selectAll();System.out.println(employees);}}//查询单个@Testpublic void select1(){Employee employee=new Employee();employee.setId(1);Employee employee1 = employee.selectById();//或者,使用这种方式也可以Employee employee2 = employee.selectById(1);System.out.println(employee1);System.out.println(employee2);//删除和该两种种方式类似,}//条件查询//注意,column是数据库字段而非实体类属性名@Testpublic void select2(){Employee employee=new Employee();List<Employee> age = employee.selectList(new EntityWrapper().eq("age", 11));System.out.println(age);}//查询总记录数,携带条件@Testpublic void select3(){Employee employee=new Employee();int age = employee.selectCount(new EntityWrapper().between("age", 10, 60));System.out.println(age);}//page,分页,可携带条件@Testpublic void select4(){Employee employee=new Employee();Page<Employee> employeePage = employee.selectPage(new Page<Employee>(1, 2), null);System.out.println(employeePage);System.out.println(employeePage.getRecords());}
gitee案例,实体类继承model
3.代码生成器
坐标
<!--模板引擎 --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.2</version></dependency>还有其他众多模板可参考官网
代码生成
@Testpublic void test() {//全局配置GlobalConfig globalConfig = new GlobalConfig();globalConfig.setAuthor("gww") //作者.setActiveRecord(true) //开启AR模式.setOutputDir("E:/projects/mybatis-plus/demo1/mybatisplus_demo3/src/main/java") //生成路径.setFileOverride(true) //文件覆盖.setIdType(IdType.AUTO) //主键策略.setServiceName("%sServer") //生成的server接口首字母是否为I .setBaseResultMap(true).setBaseColumnList(true);//数据源配置DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setDbType(DbType.MYSQL).setPassword("123456").setDriverName("com.mysql.jdbc.Driver").setUsername("root").setUrl("jdbc:mysql://localhost:3306/mp_plus");//策略配置StrategyConfig strategyConfig = new StrategyConfig();strategyConfig.setCapitalMode(true) //全局大写.setDbColumnUnderline(true) //指定表名字段是否下划线.setNaming(NamingStrategy.underline_to_camel) //数据库映射到实体的命名策略.setInclude("empty"); //生成的表
// .setTablePrefix("tab_");//包名策略配置PackageConfig packageConfig = new PackageConfig();packageConfig.setParent("com.sz").setMapper("mapper").setService("service").setController("controller").setEntity("beans").setXml("mapper");//整合配置!AutoGenerator autoGenerator = new AutoGenerator();autoGenerator.setPackageInfo(packageConfig).setStrategy(strategyConfig).setGlobalConfig(globalConfig).setDataSource(dataSourceConfig);autoGenerator.execute(); //执行生成}
执行该段代码会自动生成一些文件和类注意,生成的mapper映射文件的二级缓存记得关闭,否则很可能报错可生成mapper,service,impl,controller 其余一些配置可参考官网代码生成器生成的mapper接口继承了BaseMapper<T>接口
实体类继承了Model<T>抽象类
gitee案例参考
3.注册插件
分页插件
在 spring配置文件中的sqlSessionFactoryBean下注册<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"><!-- 数据源 --><property name="dataSource" ref="dataSource"></property><property name="configLocation" value="classpath:mybatis-config.xml"></property><!-- 别名处理 --><property name="typeAliasesPackage" value="com.atguigu.mp.beans"></property> <!-- 注入全局MP策略配置 --><property name="globalConfig" ref="globalConfiguration"></property><property name="plugins"><list><!--注册分页插件--><bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean></list></property></bean>mybati-plus已经可以使用分页了,为什么还需要分页插件呢之前不使用分页插件的话,会直接在内存中分页,会查询出大量的数据,消耗内存当进行修改操作后,可能会导致数据会不准确 使用了分页插件后,分页的写法和之前一样,只不过不是在内存中分页,而是查询的数据库
执行分析插件
作用:当有全表的数据操作是,会阻止该行为,不会报错依然在bean为sqlSessionFactoryBean的里面plugins里面添加,添加在list里面,和分页插件同个位置
<!--执行分析插件--><bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor"><property name="stopProceed" value="true"></property>
</bean>
性能分析插件
依然添加到plugins插件处
<!--性能分析插件--><bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"><property name="maxTime" value="2000"></property><!--sql执行的最大超时时间--><property name="format" value="true"></property><!--输出的sql语句格式化--></bean>
乐观锁插件
需要在表中添加一个字段 version。
并且在实体类中添加一个属性 version,并且使用@Version注解。
添加该字段的原因是,当我们的实体类修改数据库时,会将我设置的version值和数据库的值进行比对,如果相同,则操作成功。
如果不同,那么语句依然可以执行,但是改变的记录为0,不会报错
gitee案例,注册插件,更多插件移步官网
4.自定义全局配置
使用
在mapper的接口类里写自定义的方法,但是可以不需要再映射文件里写相应的sql
如 public interface EmptyMapper extends BaseMapper<Empty> {List<Empty> seleon();}没有写对应的映射文件此时,需要定义一个类区继承AutoSqlInjector类
public class MyJector extends AutoSqlInjector{@Overridepublic void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { //table表信息String sql="select * from "+table.getTableName(); 拼接成一个sqlString method="seleon"; //在mapper接口下的方法的方法名SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, mapperClass);MappedStatement mappedStatement = this.addSelectMappedStatement(mapperClass, method, sqlSource, Empty.class, table);}
}<!--将全局配置加入到spring,然后再加入全局策略配置--><bean class="com.sz.jector.MyJector" id="myJector"></bean><!-- MybatisPlus的全局策略配置--><!--加入到该全局配置策略里--> 在spring核心配置文件里 <property name="sqlInjector" ref="myJector"></property>
注意(驼峰下划线配置)
使用代码生成器生成的实体类有可能驼峰命名会无效,需要在配置一下
之前在spring配置文件配置的
<property name="dbColumnUnderline" value="true"></property>
可能无效
需要另外配置一下在mybatis-config.xml,也就是mybatis的配置文件中<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis//DTD Config 3.0//EN"
".dtd">
<configuration><!-- 全局配置 --><settings><!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典Java 属性名 aColumn 的类似映射。 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>
gitee案例,自定义全局配置,以及驼峰下划线处理
5.逻辑删除
改动
实体类添加属性@TableLogic //逻辑删除字段的注解private Integer logIc;数据库也需要添加该字段在spring配置文件中添加一个bean
<!--逻辑删除--><bean class="com.baomidou.mybatisplus.mapper.LogicSqlInjector" id="logicSqlInjector"></bean>然后在 <!-- MybatisPlus的全局策略配置-->里做以下修改注意:此时,之前做的自定义全局配置的 <!--<property name="sqlInjector" ref="myJector"></property>--> 需要注释
原因是,他们都是都一个属性,是不能同时存在两个的然后添加以下内容:<!--使用了逻辑删除,就需要把myJector注释了 ,然后还需要配置字段的值对应的状态--><property name="sqlInjector" ref="logicSqlInjector"></property><property name="logicDeleteValue" value="-1"></property> <!-- 删除的状态为-1--><property name="logicNotDeleteValue" value="1"></property> <!--没有删除的状态为1-->此时的删除,并不是真正意义上的删除,而是将该字段设置为了-1,当查询时,是查询不到该数据的,但是该数据还一直保存在数据库里
gitee案例,逻辑删除
6.公共字段填充
步骤
新建一个类
MyMetaObjectHandler 继承 MetaObjectHandler抽象类
覆写两个方法public class MyMetaObjectHandler extends MetaObjectHandler{//插入数据时填充public void insertFill(MetaObject metaObject) {Object log_ic = getFieldValByName("name", metaObject); 指的是实体类的属性if (log_ic==null){System.out.println("填充数据");setFieldValByName("name", "gww", metaObject); 当插入数据时,name属性为空时,就用值为gww的数据填充到执行的sql里,插入数据库}}//修改数据时填充public void updateFill(MetaObject metaObject) {Object log_ic = getFieldValByName("name", metaObject);if (log_ic==null){System.out.println("填充数据"); 如上,雷同,就是在修该数据的时候setFieldValByName("name", "gww", metaObject);}}
}然后将新建的类加入到spring里管理<!--数据字段填充--><bean class="com.sz.handle.MyMetaObjectHandler" id="myMetaObjectHandler"></bean>然后将该对象放到 MybatisPlus的全局策略配置里<!--数据字段填充注入--><property name="metaObjectHandler" ref="myMetaObjectHandler"></property>对应的实体类属性也要做一些修改@TableField(fill = FieldFill.INSERT_UPDATE) //添加填充属性,表示在插入和修改时无数据就填充设置好的值private String name;
gitee案例,数据自动填充
二、springboot-mybatis-plus
springboot-mybatis-plus
更多推荐
如何快速的入门mybatis
发布评论