首页 > 其他分享 >mybatisplus总结

mybatisplus总结

时间:2023-06-14 20:11:26浏览次数:42  
标签:总结 Goods mybatisplus log qw 批量 warn goods

mybatisplus 和 springboot 的集成

导入依赖

        <!--spring-boot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>

        <!--mybatis plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

配置文件

## web ##
server:
  servlet:
    context-path: /
  port: 80

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.100.66:3306/hl?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Hongkong&useSSL=false&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  mapper-locations: mapper/*.xml   #定义xml文件的位置
  type-aliases-package: com.lomi.entity  #定义实体文件的包

dao从层

public interface GoodsMapper extends BaseMapper<Goods> {

}

GoodsService层

public interface GoodsService  extends IService<Goods> {

	void add(Goods goods);


}

GoodsServiceImpl

@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService  {

	@Resource
	GoodsExMapper goodsExMapper;

	@Override
	@Transactional
	public void add(Goods goods) {
		getBaseMapper().insert(goods);
	}


}
/**
 * 定义dao文件的的包
 */
@MapperScan("com.lomi.mapper") 
@SpringBootApplication
public class MybatisplusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisplusApplication.class, args);
    }

}

GoodsMapper.xml可以不存在

用法和建议

mybatisPlus对dao层和Service都有一些默认封装,可以选择只用dao层,也可以选择dao和service层一起使用。

service的批量操作效率比拼装 foreach方式更高

mybatisPlus对dao层的封装

增删改查,分页,列表,查询数量,查询是否存在等接口

	@Override
	public void t1() {
		LambdaQueryWrapper<Goods> qw = Wrappers.lambdaQuery();
		Goods goods = Goods.randomGoods();
		Page page = new Page(1,4);


		//查询
		goodsExMapper.selectById(1668801996867579904L);
		//多个会抛出异常
		try{
			goodsExMapper.selectOne(qw);
		}catch (Exception e){
			log.warn("不止一个");
		}

		boolean exists = goodsExMapper.exists(qw);
		log.warn("是否存在{}", exists );

		Long count = goodsExMapper.selectCount(qw);
		log.warn("数量{}", count );

		List<Goods> list = goodsExMapper.selectList(qw);
		log.warn("不分页结果{}", JSONUtil.toJsonStr( list ));


		IPage selectPage = goodsExMapper.selectPage(page, qw);
		log.warn("分页结果{}", JSONUtil.toJsonStr( selectPage ));



		//添加
		goodsExMapper.insert(goods);


		//更新
		goodsExMapper.updateById( goods );
		log.warn("完成更新");


		//批量
		//批量查询(用的in,真批量,建议使用)
		List<Goods> list1 = goodsExMapper.selectBatchIds(Arrays.asList(1668805297105350656L, 1668805300435628032L));
		log.warn("批量查询{}",list1);

		//批量删除(用的in,真批量,建议使用)
		int i = goodsExMapper.deleteBatchIds(Arrays.asList(1668805297105350656L, 1668805300435628032L));
		log.warn("批量删除{}",i);


		//删除
		goodsExMapper.deleteById(1L);
		log.warn("删除Id是1的数据");
		//条件删除
		//goodsExMapper.delete(qw);
	}

mybatisPlus对service的封装

对比dao层的封装,提供里更多批量接口,提供了saveOrUpdate之类的接口,后面会体现提供的批量接口效率都很高

	@Override
	public void t1() {
		t2();
		add();
		get();
		up();
		delete();
		batch();
	}

	@Override
	@Transactional
	public void batchAdd(List<Goods> list) {
		saveBatch(list);
	}

	/**
	 * 获取当前的mapper
	 */
	private void t2() {
		GoodsMapper goodsMapper = getBaseMapper();
		log.debug( "goodsMapper:" + goodsMapper );
	}


	/**
	 * 添加
	 */
	private void add() {
		add( Goods.randomGoods() );
		save(Goods.randomGoods());
	}

	/**
	 * 查询
	 */
	private void get() {
		//用过Id查询
		Goods goods = getById(id);

		LambdaQueryWrapper<Goods> qw = Wrappers.lambdaQuery();
		qw.gt( Goods::getId,1L);
		//查询单个,多个会抛出异常
		//getOne(qw);

		//查询单个不抛出异常,得到第一个
		Goods one = getOne(qw, false);
		log.debug( "查询单个:" + one );


		//获取任意对象
		HashMap<String, Object> obj = (HashMap<String, Object>) getObj(qw, item -> {
			//item.get
			return BeanUtil.beanToMap( item );
		});
		log.debug( "查询对象封装:" + obj );


		//查询数量
		count();
		long count = count(qw);
		log.debug( "查询数量:" + count );


		//不分页查询列表
		list();
		list(qw);


		//分页查询1
		Page page = new Page(1,10);
		IPage pageList1 = page(page, qw);
		log.debug( "分页查询1:" + pageList1 );

		//分页查询2
		List<Goods> pageList2 = goodsExMapper.pageList(page);
		log.debug( "分页查询2:" + pageList2.getClass() );

	}

	Long id = 1668822727982657536L;

	/**
	 * 修改
	 */
	private void up() {
		Goods goods = getById(id);
		goods.setName("改");

		//添加或者更新
		saveOrUpdate(goods);


		//通过Id更新
		updateById(  goods );

		//查询条件更新
		LambdaUpdateWrapper<Goods> uw = Wrappers.lambdaUpdate(Goods.randomGoods());
		uw.eq( Goods::getId,1L);
		uw.set(Goods::getName,"uw名字");
		update(uw);

		//查询条件更新2
		LambdaQueryWrapper<Goods> qw = Wrappers.lambdaQuery();
		qw.eq( Goods::getId,1L);
		update(goods,qw);


	}


	/**
	 * 删除
	 */
	private void delete() {
		removeById(1L);
	}



	/**
	 * 批量接口
	 */
	private void batch() {
		//批量查询(这个用的底层的in批量查询)
		listByIds(Arrays.asList( 1L ) );


		//批量插入(1000条数据时,约比sql上拼装foreach块60倍)
		saveBatch(Arrays.asList( Goods.randomGoods(),Goods.randomGoods()  ));
		log.warn("批量插入----------------");


		//批量添加或者更新
		saveOrUpdateBatch(Arrays.asList( Goods.randomGoods(),Goods.randomGoods()  ));
		log.warn("批量插入或者更新----------------");

		//批量删除
		removeByIds( Arrays.asList( 1L,2L ) );
		log.warn("批量删除----------------");


		//批量更新
		updateBatchById( Arrays.asList( Goods.randomGoods(),Goods.randomGoods()  ) );
		log.warn("批量更新----------------");


		updateBatchById( Arrays.asList( Goods.randomGoods(),Goods.randomGoods()  ),1000 );
		log.warn("批量更新2----------------");
	}

mybatisplus不同版本的分页

不同版本启用分页插件
    /**
     * mybatisPlus 3.5以后 用这种用法
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }



    /*
     *
     * mybatis 3.3-3.4 这样用
     *
     * */
   /* @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setDbType(DbType.MYSQL);
        return paginationInterceptor;
    }*/


    /*
    *
    * mybatis 3.2以前使用这种用法
    *
    * */
    /*@Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor().setDialectType(DbType.MYSQL.getDb());
    }*/

使用分页的常见两种方式
		//直接使用mybatisplus的selectPage接口
		Page page = new Page(1,4);
		IPage selectPage = goodsExMapper.selectPage(page, qw);
		log.warn("分页结果{},{}", JSONUtil.toJsonStr( selectPage ),page.getTotal());

		//请求参数中带有Page对象就会分页
		Page page2 = new Page(1,4);
		List<Goods> list2 = goodsExMapper.pageList(page2);
		log.warn("分页结果2{},{}", JSONUtil.toJsonStr( list2 ),page2.getTotal());

批量service层批量接口和在sql上拼接foreach效率差异

结论service层批量插入约是sql上凭借foreach的60倍

foreach方式
    <insert id="addBatch">
        insert into goods (id,
        name,
        stock,
        des,
        des2,
        data,
        create_date)
        values
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.id,jdbcType=BIGINT},
            #{item.name,jdbcType=VARCHAR},
            #{item.stock,jdbcType=INTEGER},
            #{item.des,jdbcType=VARCHAR},
            #{item.des2,jdbcType=VARCHAR},
            #{item.data,jdbcType=LONGVARCHAR},
            #{item.createDate,jdbcType=TIMESTAMP})
        </foreach>
    </insert>

	@Override
	@Transactional
	public void batchAdd(List<Goods> list) {
		goodsExMapper.addBatch(list);
	}
使用mybatisplus service封装的方式
	@Override
	@Transactional
	public void batchAdd(List<Goods> list) {
		saveBatch(list);
	}

记录运行时间的测试代码
	/**
	 * 批量
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="t3", method= {RequestMethod.GET})
	public String t3() throws Exception{

		List<Goods> list1 = new ArrayList<>();
		List<Goods> list2 = new ArrayList<>();

		Stream.generate(Goods::randomGoods ).limit(1000).forEach( item-> list1.add( item ) );
		Stream.generate(Goods::randomGoods ).limit(1000).forEach( item-> list2.add( item ) );



		Long time1 = System.currentTimeMillis();
		//foreach方式
		iGoodsService.batchAdd(list1);
		Long time2 = System.currentTimeMillis();

		//mybatisplus封装的批量插入
		goodsService.batchAdd(list2);
		Long time3 = System.currentTimeMillis();

		log.warn("dao层子写批量:{}", time2-time1);
		log.warn("mybatisplus——service封装的批量:{}",time3-time2 );


		return "OK";
	}
三次运行的结果分别是
2023-06-14 14:28:23.992  WARN 17156 --- [p-nio-80-exec-2] c.lomi.controller.MyBatisPlusController  : dao层子写批量:13187
2023-06-14 14:28:23.993  WARN 17156 --- [p-nio-80-exec-2] c.lomi.controller.MyBatisPlusController  : mybatisplus——service封装的批量:211



2023-06-14 14:29:00.470  WARN 17156 --- [p-nio-80-exec-9] c.lomi.controller.MyBatisPlusController  : dao层子写批量:12562
2023-06-14 14:29:00.470  WARN 17156 --- [p-nio-80-exec-9] c.lomi.controller.MyBatisPlusController  : mybatisplus——service封装的批量:183



2023-06-14 14:29:25.417  WARN 17156 --- [p-nio-80-exec-5] c.lomi.controller.MyBatisPlusController  : dao层子写批量:13079
2023-06-14 14:29:25.417  WARN 17156 --- [p-nio-80-exec-5] c.lomi.controller.MyBatisPlusController  : mybatisplus——service封装的批量:168


mybatisplus乐观锁

    /**
     * mybatisPlus 3.5以后 用这种用法
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //乐观锁插件
        interceptor.addInnerInterceptor( new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

在实体上标记version

@Version
private Integer version;

然后再更新的时候就会带上 version的条件,如果version是null,那么乐观锁不会生效

	@Override
	public void updatebyVersion() {
		Goods goods = getById(1668873830610841600L);
		goods.setName("改1");

		log.warn("打印1,{},{}",goods.getVersion(),goods.getName());
		boolean rt1 = updateById( goods );
		log.warn("打印2,{},{}",goods.getVersion(),goods.getName());
		log.warn("更新结果{}",rt1);


		goods.setName("改2");

		log.warn("打印3,{},{}",goods.getVersion(),goods.getName());
		boolean rt2 = updateById(goods);
		log.warn("打印4,{},{}",goods.getVersion(),goods.getName());
		log.warn("更新结果{}",rt2);


		//删除的时候不会带上乐观锁
		removeById(goods);
	}

注解方式的sql

这不是mybatisplus的,是mybatis的语法,并且个人不推荐用注解形式的sql,xml 格式的sql 比 注解方式的sql 可读性搞很多,尽量写到xml里面去,对齐格式,方便阅读,个人建议优先使用 xml方式的sql,可以少量使用QueryWrapper,UpdateWrapper这种面向对象的方式,namedsql方式建议少使用

	//使用#{}获取参数
	@Select("select * from goods where id = #{id}")
	Goods querById_nameSql(@Param("id") Long id);


	@Update("update goods set name = #{param.name} where id = #{param.id}")
	int update_namedsql(@Param("param") Goods param);

	//参数有 Page对象就会分页
	@Select("select * from goods")
	List<Goods> queryPage_namedsql(@Param("name") String name,Page page);


	/**
	 * ${ew.sqlSelect} :查询字段的部分的sql,来自接口 Query 的getSqlSelect方法,查询语句才能用
	 * ${ew.sqlSet} set 部分的sql ,来自接口 Update的getSqlSet方法
	 * ${ew.sqlSegment} where后面的 sql ,来自接口 ISqlSegment的getSqlSegment方法
	 * Constants.WRAPPER里面的参数都是可以通过 ${}方式取到
	 */
	@Update("update goods set ${ew.sqlSet}   where ${ew.sqlSegment}")
	int updateParam_namedsql(@Param(Constants.WRAPPER) Wrapper<Goods> wp, Page page);

mybatisQueryWrapper or方式的查询

	/**
	 * 默认都说and
	 * 使用  and 或者 or 等于建立了一个子条件,同一层有多个条件会添加括号
	 */
	@Override
	public void orQuery() {

		//WHERE (name = ? OR name = ?)
		LambdaQueryWrapper<Goods> query1 = Wrappers.lambdaQuery();
		query1.eq( Goods::getName,"name1" );
		LambdaQueryWrapper<Goods> query12 = query1.or();
		query12.eq(Goods::getName,"name2");
		List<Goods> list = list(query1);


		// WHERE (name = ? AND (id = ? AND des = ? OR id = ? AND des = ?))
		//外面的条件
		LambdaQueryWrapper<Goods> query2 = Wrappers.lambdaQuery();
		query2.eq( Goods::getName,"name1" );
		LambdaQueryWrapper<Goods> and = query2.and(qw->{
			//子条件1
			qw.eq( Goods::getId,1 );
			qw.eq( Goods::getDes,"des1" );

			//子条件2
			LambdaQueryWrapper<Goods> qwor = qw.or();
			qwor.eq(  Goods::getId,2 );
			qwor.eq( Goods::getDes,"des2" );


		});
		List<Goods> list2 = list(query2);



		// WHERE (name = ? AND ((id = ? AND des = ?) OR (id = ? AND des = ?)))
		//外面的条件
		LambdaQueryWrapper<Goods> query3 = Wrappers.lambdaQuery();
		query3.eq( Goods::getName,"name1" );
		LambdaQueryWrapper<Goods> and3 = query3.and(qw->{
			//子条件1
			qw.and(item->{
				item.eq( Goods::getId,1 );
				item.eq( Goods::getDes,"des1" );
			});

			//子条件2
			LambdaQueryWrapper<Goods> qwor = qw.or();
			qwor.or(item->{
				item.eq(  Goods::getId,2 );
				item.eq( Goods::getDes,"des2" );
			});

		});
		List<Goods> list3 = list(query3);

	}

标签:总结,Goods,mybatisplus,log,qw,批量,warn,goods
From: https://www.cnblogs.com/cxygg/p/17481251.html

相关文章

  • 图解机器学习总结——1、基本概念
    序言:近期主要帮同事讲解《图解机器学习》,刚拿到这本书觉得内容相比较平常使用的机器学习算法,很多地方讲解得比较奇怪,在认真的读完后,觉得还是有很多重要的东西,因此读了书就想把知识点整理出来,加上一些自己对各种算法的认识,因此这个系列里面有一些个人的理解,若有不对的地方,还请不吝指......
  • C/C++——map的基本操作总结
    标准库map类型是一种以键-值(key-value)存储的数据类型。以下分别从以下的几个方面总结:map对象的定义和初始化map对象的基本操作,主要包括添加元素,遍历等1、pair类型1.1、pair类型的定义和初始化pair类型是在有文件utility中定义的,pair类型包含了两个数据值,通常有以下的一些定义和初......
  • C/C++——vector的基本操作总结
    标准库vector类型是C++中使用较多的一种类模板,vector类型相当于一种动态的容器,在vector中主要有一些基本的操作,接下来分别从以下的几个方面总结:vector对象的定义和初始化vector对象的基本操作,主要包括添加元素,遍历等1、vector对象的定义和初始化在vector中主要有四种定义和初始化的......
  • Handler机制实现原理总结
    Handler一般用于线程间通信,如常用的子线程使用handler让主线程更新UI。那么这是怎么实现的呢?我们先把这个大问题分解成多个小问题:post();postDelayed();sendMessage();sendEmptyMessage();等方法有什么不同?Handler为什么需要一个Looper,为什么它不能为空?Handler为什么可以做到......
  • MyBatisPlus_动态更新
    场景:项目整合了mybatisplus,进行update更新,前端传值为空时,数据库也进行了更新,导致原来的值丢失。解决方案:在实体类上使用@TableField注解/*联系人手机号码*/@TableField(updateStrategy=FieldStrategy.NOT_EMPTY)privateStringphone;这样,当前端传过来的phone参数为......
  • 模块知识点总结
    当讲解Python模块时,可以按照以下详细的内容和示例进行讲解:一、什么是模块?A.定义模块:模块是一个包含了Python代码的文件,可以包含变量、函数、类和可执行的代码。模块通过将代码组织成单独的文件,方便重复使用和管理。B.模块的作用和意义:提供了代码的重用性,避免重复编写相......
  • 20230612刷题总结
    2023/06/12刷题总结A-DoubleCola如果n在1到5之间先单独判断是谁.如果大于5之后,用一个cnt记录当前这一组由几个人排在一起,然后使用循环每次动态的删除人数,直到找到n在那一组,然后将剩下的n直接整除pow(2,cnt)就可以了.#include<bits/stdc++.h>#defineintlonglong#d......
  • 《重构-改善既有代码的设计》个人总结笔记
    重构refacting在不改变代码外在行为的前提下,对代码内部结构进行修改。是一种代码的整理方法,本质上就是在代码写好之后改进设计。每一次修改,完成之后都要进行测试,因而在重构之前,准备一套较为信赖的测试数据,以保证重构的正确性很重要提高代码的可修改性,降低修改成本,提高阅读性营......
  • ASH分析方法总结
    gv$active_session_history会每秒钟将数据库所有节点的ActiveSession采样一次,而dba_hist_active_sess_history则会将gv$active_session_history里的数据每10秒采样一次并持久化保存。基于这个特征,我们可以通过分析dba_hist_active_sess_history的Session采样情况,来定位问题发生的......
  • CF 932 E. Team Work 第二类斯特林数总结
    求解\(\sum_{x=1}^nC(n,x)x^k,n\le10^9,k\le5000\)第二类斯特林数n个不同的小球放入k个相同的盒子的方案数\(S(n,k)\),盒子非空显然有\(S(n,k)=S(n-1,k-1)+k\cdotS(n-1,k)\)注意边界\(S(n,0)=[n==0],S(n,1)=1\)考虑到\(x^k\)可以利用第二类斯特林数化简\(x^k=\sum_{i=1}^{x......