当前位置: 首页 > news >正文

网站源码模板下载中石油七建设公司官网

网站源码模板下载,中石油七建设公司官网,网名大全,注册公司去哪个网站Mybatis-Plus 使用场景 大家在日常开发中应该能发现#xff0c;单表的CRUD功能代码重复度很高#xff0c;也没有什么难度。而这部分代码量往往比较大#xff0c;开发起来比较费时。 因此#xff0c;目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国…Mybatis-Plus 使用场景 大家在日常开发中应该能发现单表的CRUD功能代码重复度很高也没有什么难度。而这部分代码量往往比较大开发起来比较费时。 因此目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的一个组件就是MybatisPlus. 快速入门 Mybatis-Plus官方网站 导入依赖 dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.3.1/version /dependency定义Mapper 为了简化单表CRUDMybatisPlus提供了一个基础的BaseMapper接口其中已经实现了单表的CRUD 因此我们自定义的Mapper只要实现了这个BaseMapper就无需自己实现单表CRUD了。 修改mp-demo中的com.itheima.mp.mapper包下的UserMapper接口让其继承BaseMapper package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.itheima.mp.domain.po.User;public interface UserMapper extends BaseMapperUser { }测试 package com.itheima.mp.mapper;import com.itheima.mp.domain.po.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime; import java.util.List;SpringBootTest class UserMapperTest {Autowiredprivate UserMapper userMapper;Testvoid testInsert() {User user new User();user.setId(5L);user.setUsername(Lucy);user.setPassword(123);user.setPhone(18688990011);user.setBalance(200);user.setInfo({\age\: 24, \intro\: \英文老师\, \gender\: \female\});user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userMapper.insert(user);}Testvoid testSelectById() {User user userMapper.selectById(5L);System.out.println(user user);}Testvoid testSelectByIds() {ListUser users userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L, 5L));users.forEach(System.out::println);}Testvoid testUpdateById() {User user new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}Testvoid testDelete() {userMapper.deleteById(5L);} }常见注解 TableName 描述表名注解标识实体类对应的表使用位置实体类 TableName(user) public class User {private Long id;private String name; }属性类型必须指定默认值描述valueString否“”表名schemaString否“”schemakeepGlobalPrefixboolean否false是否保持使用全局的 tablePrefix 的值当全局 tablePrefix 生效时resultMapString否“”xml 中 resultMap 的 id用于满足特定类型的实体类对象绑定autoResultMapboolean否false是否自动构建 resultMap 并使用如果设置 resultMap 则不会进行 resultMap 的自动构建与注入excludePropertyString[]否{}需要排除的属性名 since 3.3.1 TableId 描述主键注解标识实体类中的主键字段使用位置实体类的主键字段 TableName(user) public class User {TableIdprivate Long id;private String name; }TableId注解支持两个属性 属性类型必须指定默认值描述valueString否“”表名typeEnum否IdType.NONE指定主键类型 IdType支持的类型有 值描述AUTO数据库 ID 自增NONE无状态该类型为未设置主键类型注解里等于跟随全局全局里约等于 INPUTINPUTinsert 前自行 set 主键值ASSIGN_ID分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)ASSIGN_UUID分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法)ID_WORKER分布式全局唯一 ID 长整型类型(please use ASSIGN_ID)UUID32 位 UUID 字符串(please use ASSIGN_UUID)ID_WORKER_STR分布式全局唯一 ID 字符串类型(please use ASSIGN_ID) 这里比较常见的有三种 AUTO利用数据库的id自增长INPUT手动生成idASSIGN_ID雪花算法生成Long类型的全局唯一id这是默认的ID策略 TableField TableName(user) public class User {TableIdprivate Long id;private String name;private Integer age;TableField(is_married)private Boolean isMarried;TableField(concat)private String concat; }一般情况下我们并不需要给字段添加TableField注解一些特殊情况除外 成员变量名与数据库字段名不一致成员变量是以isXXX命名按照JavaBean的规范MybatisPlus识别字段时会把is去除这就导致与数据库不符。成员变量名与数据库一致但是与数据库的关键字冲突。使用TableField注解给字段名添加转义字符 属性类型必填默认值描述valueString否“”数据库字段名existboolean否true是否为数据库表字段conditionString否“”字段 where 实体查询比较条件有值设置则按设置的值为准没有则为默认全局的 %s#{%s}参考(opens new window)updateString否“”字段 update set 部分注入例如当在version字段上注解update“%s1” 表示更新时会 set versionversion1 该属性优先级高于 el 属性insertStrategyEnum否FieldStrategy.DEFAULT举例NOT_NULL insert into table_a(column) values (#{columnProperty})updateStrategyEnum否FieldStrategy.DEFAULT举例IGNORED update table_a set column#{columnProperty}whereStrategyEnum否FieldStrategy.DEFAULT举例NOT_EMPTY where column#{columnProperty}fillEnum否FieldFill.DEFAULT字段自动填充策略selectboolean否true是否进行 select 查询keepGlobalFormatboolean否false是否保持使用全局的 format 进行处理jdbcTypeJdbcType否JdbcType.UNDEFINEDJDBC 类型 (该默认值不代表会按照该值生效)typeHandlerTypeHander否类型处理器 (该默认值不代表会按照该值生效)numericScaleString否“”指定小数点后保留的位数 核心功能 条件构造器 除了新增以外修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外还支持更加复杂的where条件。 Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法 QueryWrapper 无论是修改、删除、查询都可以使用QueryWrapper来构建查询条件。接下来看一些例子 查询查询出名字中带o的存款大于等于1000元的人。代码如下 Test void testQueryWrapper() {// 1.构建查询条件 where name like %o% AND balance 1000QueryWrapperUser wrapper new QueryWrapperUser().select(id, username, info, balance).like(username, o).ge(balance, 1000);// 2.查询数据ListUser users userMapper.selectList(wrapper);users.forEach(System.out::println); }更新更新用户名为jack的用户的余额为2000代码如下 Test void testUpdateByQueryWrapper() {// 1.构建查询条件 where name JackQueryWrapperUser wrapper new QueryWrapperUser().eq(username, Jack);// 2.更新数据user中非null字段都会作为set语句User user new User();user.setBalance(2000);userMapper.update(user, wrapper); }UpdateWrapper 基于BaseMapper中的update方法更新时只能直接赋值对于一些复杂的需求就难以实现。 例如更新id为1,2,4的用户的余额扣200对应的SQL应该是 UPDATE user SET balance balance - 200 WHERE id in (1, 2, 4)SET的赋值结果是基于字段现有值的这个时候就要利用UpdateWrapper中的setSql功能了 Test void testUpdateWrapper() {ListLong ids List.of(1L, 2L, 4L);// 1.生成SQLUpdateWrapperUser wrapper new UpdateWrapperUser().setSql(balance balance - 200) // SET balance balance - 200.in(id, ids); // WHERE id in (1, 2, 4)// 2.更新注意第一个参数可以给null也就是不填更新字段和数据// 而是基于UpdateWrapper中的setSQL来更新userMapper.update(null, wrapper); }LambdaQueryWrapper 无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称会出现字符串魔法值。这在编程规范中显然是不推荐的。 那怎么样才能不写字段名又能知道字段名呢 其中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给MybatisPlus它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper包含两个 LambdaQueryWrapperLambdaUpdateWrapper 分别对应QueryWrapper和UpdateWrapper Test void testLambdaQueryWrapper() {// 1.构建条件 WHERE username LIKE %o% AND balance 1000QueryWrapperUser wrapper new QueryWrapper();wrapper.lambda().select(User::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, o).ge(User::getBalance, 1000);// 2.查询ListUser users userMapper.selectList(wrapper);users.forEach(System.out::println); }自定义SQL 这种写法在某些企业也是不允许的因为SQL语句最好都维护在持久层而不是业务层。就当前案例来说由于条件是in语句只能将SQL写在Mapper.xml文件利用foreach来生成动态SQL。 这实在是太麻烦了。假如查询条件更复杂动态SQL的编写也会更加复杂。 基本用法 Test void testCustomWrapper() {// 1.准备自定义查询条件ListLong ids List.of(1L, 2L, 4L);QueryWrapperUser wrapper new QueryWrapperUser().in(id, ids);// 2.调用mapper的自定义方法直接传递WrapperuserMapper.deductBalanceByIds(200, wrapper); }package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.itheima.mp.domain.po.User; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; import org.apache.ibatis.annotations.Param;public interface UserMapper extends BaseMapperUser {Select(UPDATE user SET balance balance - #{money} ${ew.customSqlSegment})void deductBalanceByIds(Param(money) int money, Param(ew) QueryWrapperUser wrapper); }我们可以吧自定义的条件以参数的方式传递下去 Service接口 MybatisPlus不仅提供了BaseMapper还提供了通用的Service接口及默认实现封装了一些常用的service模板方法。 通用接口为IService默认实现为ServiceImpl其中封装的方法可以分为以下几类 save新增remove删除update更新get查询单个结果list查询集合结果count计数page分页查询 CRUD 新增 save是新增单个元素saveBatch是批量新增saveOrUpdate是根据id判断如果数据存在就更新不存在则新增saveOrUpdateBatch是批量的新增或修改 删除 removeById根据id删除removeByIds根据id批量删除removeByMap根据Map中的键值对为条件删除remove(Wrapper)根据Wrapper条件删除removeBatchByIds暂不支持 修改 updateById根据id修改update(Wrapper)根据UpdateWrapper修改Wrapper中包含set和where部分update(TWrapper)按照T内的数据修改与Wrapper匹配到的数据updateBatchById根据id批量修改 Get getById根据id查询1条数据getOne(Wrapper)根据Wrapper查询1条数据getBaseMapper获取Service内的BaseMapper实现某些时候需要直接调用Mapper内的自定义SQL时可以用这个方法获取到Mapper List listByIds根据id批量查询list(Wrapper)根据Wrapper条件查询多条数据list()查询所有 Count count()统计所有数量count(Wrapper)统计符合Wrapper条件的数据数量 getBaseMapper 当我们在service中要调用Mapper中自定义SQL时就必须获取service对应的Mapper就可以通过这个方法 基本用法 由于Service中经常需要定义与业务有关的自定义方法因此我们不能直接使用IService而是自定义Service接口然后继承IService以拓展方法。同时让自定义的Service实现类继承ServiceImpl这样就不用自己实现IService中的接口了。 首先定义IUserService继承IService package com.itheima.mp.service;import com.baomidou.mybatisplus.extension.service.IService; import com.itheima.mp.domain.po.User;public interface IUserService extends IServiceUser {// 拓展自定义方法 }package com.itheima.mp.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itheima.mp.domain.po.User; import com.itheima.mp.domain.po.service.IUserService; import com.itheima.mp.mapper.UserMapper; import org.springframework.stereotype.Service;Service public class UserServiceImpl extends ServiceImplUserMapper, Userimplements IUserService { }Lambda IService中还提供了Lambda功能来简化我们的复杂查询及更新功能。 GetMapping(/list) ApiOperation(根据id集合查询用户) public ListUserVO queryUsers(UserQuery query){// 1.组织条件String username query.getName();Integer status query.getStatus();Integer minBalance query.getMinBalance();Integer maxBalance query.getMaxBalance();LambdaQueryWrapperUser wrapper new QueryWrapperUser().lambda().like(username ! null, User::getUsername, username).eq(status ! null, User::getStatus, status).ge(minBalance ! null, User::getBalance, minBalance).le(maxBalance ! null, User::getBalance, maxBalance);// 2.查询用户ListUser users userService.list(wrapper);// 3.处理voreturn BeanUtil.copyToList(users, UserVO.class); }在组织查询条件的时候我们加入了 username ! null 这样的参数意思就是当条件成立时才会添加这个查询条件类似Mybatis的mapper.xml文件中的标签。这样就实现了动态查询条件效果了。 不过上述条件构建的代码太麻烦了。 因此Service中对LambdaQueryWrapper和LambdaUpdateWrapper的用法进一步做了简化。我们无需自己通过new的方式来创建Wrapper而是直接调用lambdaQuery和lambdaUpdate方法 GetMapping(/list) ApiOperation(根据id集合查询用户) public ListUserVO queryUsers(UserQuery query){// 1.组织条件String username query.getName();Integer status query.getStatus();Integer minBalance query.getMinBalance();Integer maxBalance query.getMaxBalance();// 2.查询用户ListUser users userService.lambdaQuery().like(username ! null, User::getUsername, username).eq(status ! null, User::getStatus, status).ge(minBalance ! null, User::getBalance, minBalance).le(maxBalance ! null, User::getBalance, maxBalance).list();// 3.处理voreturn BeanUtil.copyToList(users, UserVO.class); }.one()最多1个结果.list()返回集合结果.count()返回计数结果 Override Transactional public void deductBalance(Long id, Integer money) {// 1.查询用户User user getById(id);// 2.校验用户状态if (user null || user.getStatus() 2) {throw new RuntimeException(用户状态异常);}// 3.校验余额是否充足if (user.getBalance() money) {throw new RuntimeException(用户余额不足);}// 4.扣减余额 update tb_user set balance balance - ?int remainBalance user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance) // 更新余额.set(remainBalance 0, User::getStatus, 2) // 动态判断是否更新status.eq(User::getId, id).eq(User::getBalance, user.getBalance()) // 乐观锁.update(); }上面代码我们看到在对余额进行更新的时候我们对用户余额进行判断也就是说我们在扣减用户余额时如果发现剩余余额为0则应该将status修改为2这就是说update语句的set部分是动态的。 批量新增 首先我们用逐条加入数据来测试 Test void testSaveOneByOne() {long b System.currentTimeMillis();for (int i 1; i 100000; i) {userService.save(buildUser(i));}long e System.currentTimeMillis();System.out.println(耗时 (e - b)); }private User buildUser(int i) {User user new User();user.setUsername(user_ i);user.setPassword(123);user.setPhone( (18688190000L i));user.setBalance(2000);user.setInfo({\age\: 24, \intro\: \英文老师\, \gender\: \female\});user.setCreateTime(LocalDateTime.now());user.setUpdateTime(user.getCreateTime());return user; }通过执行时长我们看到耗时非常长达到了20多秒 然后再试试MybatisPlus的批处理 Test void testSaveBatch() {// 准备10万条数据ListUser list new ArrayList(1000);long b System.currentTimeMillis();for (int i 1; i 100000; i) {list.add(buildUser(i));// 每1000条批量插入一次if (i % 1000 0) {userService.saveBatch(list);list.clear();}}long e System.currentTimeMillis();System.out.println(耗时 (e - b)); }速度比之前快了快十倍左右我们继续看MybatisPlus源码 Transactional(rollbackFor Exception.class) Override public boolean saveBatch(CollectionT entityList, int batchSize) {String sqlStatement getSqlStatement(SqlMethod.INSERT_ONE);return executeBatch(entityList, batchSize, (sqlSession, entity) - sqlSession.insert(sqlStatement, entity)); } // ...SqlHelper public static E boolean executeBatch(Class? entityClass, Log log, CollectionE list, int batchSize, BiConsumerSqlSession, E consumer) {Assert.isFalse(batchSize 1, batchSize must not be less than one);return !CollectionUtils.isEmpty(list) executeBatch(entityClass, log, sqlSession - {int size list.size();int idxLimit Math.min(batchSize, size);int i 1;for (E element : list) {consumer.accept(sqlSession, element);if (i idxLimit) {sqlSession.flushStatements();idxLimit Math.min(idxLimit batchSize, size);}i;}}); }可以发现其实MybatisPlus的批处理是基于PrepareStatement的预编译模式然后批量提交最终在数据库执行时还是会有多条insert语句逐条插入数据。SQL类似这样 Preparing: INSERT INTO user ( username, password, phone, info, balance, create_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ? ) Parameters: user_1, 123, 18688190001, , 2000, 2023-07-01, 2023-07-01 Parameters: user_2, 123, 18688190002, , 2000, 2023-07-01, 2023-07-01 Parameters: user_3, 123, 18688190003, , 2000, 2023-07-01, 2023-07-01那么如果想要得到很好的性能我们最好把Sql编为一句 INSERT INTO user ( username, password, phone, info, balance, create_time, update_time ) VALUES (user_1, 123, 18688190001, , 2000, 2023-07-01, 2023-07-01), (user_2, 123, 18688190002, , 2000, 2023-07-01, 2023-07-01), (user_3, 123, 18688190003, , 2000, 2023-07-01, 2023-07-01), (user_4, 123, 18688190004, , 2000, 2023-07-01, 2023-07-01);该怎么做呢 MySQL的客户端连接参数中有这样的一个参数rewriteBatchedStatements。顾名思义就是重写批处理的statement语句。参考文档文档 这个参数的默认值是false我们需要修改连接参数将其配置为true 修改项目中的application.yml文件在jdbc的url后面添加参数rewriteBatchedStatementstrue: spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mp?useUnicodetruecharacterEncodingUTF-8autoReconnecttrueserverTimezoneAsia/ShanghairewriteBatchedStatementstruedriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: MySQL123拓展功能 代码生成 在使用MybatisPlus以后基础的Mapper、Service、PO代码相对固定重复编写也比较麻烦。因此MybatisPlus官方提供了代码生成器根据数据库表结构生成PO、Mapper、Service等相关代码。只不过代码生成器同样要编码使用也很麻烦。 安装插件 使用 然后再次点击Idea顶部菜单中的other然后选择Code Generator: 静态工具 有的时候Service之间也会相互调用为了避免出现循环依赖问题MybatisPlus提供一个静态工具类Db其中的一些静态方法与IService中方法签名基本一致也可以帮助我们实现CRUD功能 demo Test void testDbGet() {User user Db.getById(1L, User.class);System.out.println(user); }Test void testDbList() {// 利用Db实现复杂条件查询ListUser list Db.lambdaQuery(User.class).like(User::getUsername, o).ge(User::getBalance, 1000).list();list.forEach(System.out::println); }Test void testDbUpdate() {Db.lambdaUpdate(User.class).set(User::getBalance, 2000).eq(User::getUsername, Rose); }逻辑删除 对于一些比较重要的数据我们往往会采用逻辑删除的方案即 在表中添加一个字段标记数据是否被删除当删除数据时把标记置为true查询时过滤掉标记为true的数据 一旦采用了逻辑删除所有的查询和删除逻辑都要跟着变化非常麻烦。 为了解决这个问题MybatisPlus就添加了对逻辑删除的支持。 配置 mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)通用枚举 我们定义一个枚举类 package com.itheima.mp.enums;import com.baomidou.mybatisplus.annotation.EnumValue; import lombok.Getter;Getter public enum UserStatus {NORMAL(1, 正常),FREEZE(2, 冻结);private final int value;private final String desc;UserStatus(int value, String desc) {this.value value;this.desc desc;} }要让MybatisPlus处理枚举与数据库类型自动转换我们必须告诉MybatisPlus枚举中的哪个字段的值作为数据库值。 MybatisPlus提供了EnumValue注解来标记枚举属性 配置枚举处理器 mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandlerJSON类型处理器 数据库有一个字段是JSON类型的但是在Java当中我们没有JSON类型的类目前我们只能用JSON来处理 这样一来我们要读取info中的属性时就非常不方便。如果要方便获取info的类型最好是一个Map或者实体类。 而一旦我们把info改为对象类型就需要在写入数据库时手动转为String再读取数据库时手动转换为对象这会非常麻烦。 因此MybatisPlus提供了很多特殊类型字段的类型处理器解决特殊字段类型与数据库类型转换的问题。例如处理JSON就可以使用JacksonTypeHandler处理器。 我们先定义一个与Json格式相同的实体类 package com.itheima.mp.domain.po;import lombok.Data;Data public class UserInfo {private Integer age;private String intro;private String gender; }接下来将User类的info字段修改为UserInfo类型并声明类型处理器 同时在User类上添加一个注解声明自动映射 分页插件 配置分页插件 创建一个配置类 package com.itheima.mp.config;import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class MybatisConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {// 初始化核心插件MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();// 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;} }使用 Test void testPageQuery() {// 1.分页查询new Page()的两个参数分别是页码、每页大小PageUser p userService.page(new Page(2, 2));// 2.总条数System.out.println(total p.getTotal());// 3.总页数System.out.println(pages p.getPages());// 4.数据ListUser records p.getRecords();records.forEach(System.out::println); }指定排序规则 int pageNo 1, pageSize 5; // 分页参数 PageUser page Page.of(pageNo, pageSize); // 排序参数, 通过OrderItem来指定 page.addOrder(new OrderItem(balance, false));userService.page(page);简化实体类 从上面开发我们可以看到从Query到Page是非常麻烦的 package com.itheima.mp.domain.query;import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.Data;Data public class PageQuery {private Integer pageNo;private Integer pageSize;private String sortBy;private Boolean isAsc;public T PageT toMpPage(OrderItem ... orders){// 1.分页条件PageT p Page.of(pageNo, pageSize);// 2.排序条件// 2.1.先看前端有没有传排序字段if (sortBy ! null) {p.addOrder(new OrderItem(sortBy, isAsc));return p;}// 2.2.再看有没有手动指定排序字段if(orders ! null){p.addOrder(orders);}return p;}public T PageT toMpPage(String defaultSortBy, boolean isAsc){return this.toMpPage(new OrderItem(defaultSortBy, isAsc));}public T PageT toMpPageDefaultSortByCreateTimeDesc() {return toMpPage(create_time, false);}public T PageT toMpPageDefaultSortByUpdateTimeDesc() {return toMpPage(update_time, false);} }那么我们就可以在里面添加一些方法简化转化 在查询出分页结果后数据的非空校验数据的vo转换都是模板代码编写起来很麻烦。 我们完全可以将其封装到PageDTO的工具方法中简化整个过程 package com.itheima.mp.domain.dto;import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors;Data NoArgsConstructor AllArgsConstructor public class PageDTOV {private Long total;private Long pages;private ListV list;/*** 返回空分页结果* param p MybatisPlus的分页结果* param V 目标VO类型* param P 原始PO类型* return VO的分页对象*/public static V, P PageDTOV empty(PageP p){return new PageDTO(p.getTotal(), p.getPages(), Collections.emptyList());}/*** 将MybatisPlus分页结果转为 VO分页结果* param p MybatisPlus的分页结果* param voClass 目标VO类型的字节码* param V 目标VO类型* param P 原始PO类型* return VO的分页对象*/public static V, P PageDTOV of(PageP p, ClassV voClass) {// 1.非空校验ListP records p.getRecords();if (records null || records.size() 0) {// 无数据返回空结果return empty(p);}// 2.数据转换ListV vos BeanUtil.copyToList(records, voClass);// 3.封装返回return new PageDTO(p.getTotal(), p.getPages(), vos);}/*** 将MybatisPlus分页结果转为 VO分页结果允许用户自定义PO到VO的转换方式* param p MybatisPlus的分页结果* param convertor PO到VO的转换函数* param V 目标VO类型* param P 原始PO类型* return VO的分页对象*/public static V, P PageDTOV of(PageP p, FunctionP, V convertor) {// 1.非空校验ListP records p.getRecords();if (records null || records.size() 0) {// 无数据返回空结果return empty(p);}// 2.数据转换ListV vos records.stream().map(convertor).collect(Collectors.toList());// 3.封装返回return new PageDTO(p.getTotal(), p.getPages(), vos);} }
http://www.pierceye.com/news/55027/

相关文章:

  • 天津哪里做网站最好网页微信版登录
  • 替别人做网站管理员怎么做seo网站推广
  • 商城网站建设都需要多少钱济南工装定制公司
  • 住房和城乡建设网站 上海图片生成链接的网站
  • 郑州快速建站价格猎聘网招聘官网app
  • 网站栏目标签如何调用电子商务网站开发实战视频
  • 在网站上投放广告世界杯哪个网站做代理
  • 商务网站建设过程中应对可能遇到的风险引流推广的句子
  • 金华企业网站推广推广普通话在哪一年
  • seo网站关键词排名提升100元网站建设
  • 帮做试卷的网站做网站读什么专业
  • 江苏网站制作洞头区网站建设收费
  • 江西建设银行招聘网站建设企业网站企业网上银行官网官方
  • 电话销售做网站打官司崇左北京网站建设
  • 建专业外贸网站网站建设销售实习报告
  • c网站开发案例详解有没有可以看的网址
  • 服务好的南昌网站制作如何设计一个网络
  • 比较好的网站开发团队什么叫前端什么叫后端
  • 怎么建个人网页广州网站建设优化公司
  • 团队网站模板视频点播网站开发
  • 优质的网站建设wordpress编辑器怎么变
  • 龙岩网站建设要多少费用企业网关路由器怎么设置
  • 有哪些网站做的比较好看wordpress 文章不显示图片
  • 融资网站建设重点wordpress 邮件认证
  • 美橙互联网站建设案例正能量软件不良网站直播
  • 有哪些网站做外贸的wordpress 积分会员
  • 我的世界做图片的网站南昌网站定制
  • 南京外贸网站建设公司排名商家版微信小程序怎么弄
  • 廊坊网站建设方案托管燕郊网站制作
  • 莆田网站制作设计网站开发需求确认书