如何快速的入门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.SqlSessionFactoryBean
		MP提供的: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);  设置条件为null
		System.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);设置条件为null
		System.out.println("查询记录数"+integer);


      //  new Page<Employee>(1, 2) 设置查看第一页,显示两条数据
        List<Employee> emps =employeeMapper.selectPage(new Page<Employee>(1, 2),null)条件为null
        System.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.com");
		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.com");
		//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  查询全部
	@Test
	public void select(){
		Employee employee=new Employee();
		List<Employee> employees = employee.selectAll();
		System.out.println(employees);
	}


	}

//查询单个
	@Test
	public 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是数据库字段而非实体类属性名
	@Test
	public void select2(){
		Employee employee=new Employee();
		List<Employee> age = employee.selectList(new EntityWrapper().eq("age", 11));
		System.out.println(age);
	}



	//查询总记录数,携带条件
	@Test
	public void select3(){
		Employee employee=new Employee();
		int age = employee.selectCount(new EntityWrapper().between("age", 10, 60));
		System.out.println(age);
	}


//page,分页,可携带条件

	@Test
	public 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>
        
还有其他众多模板可参考官网

代码生成

 @Test
    public 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{
    @Override
    public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?>     
          modelClass, TableInfo table) {    //table表信息

        String sql="select * from "+table.getTableName(); 拼接成一个sql
        String 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.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值