• 如何用函数式优雅的写一个增删改查@落雨


    如何用函数式优雅的写一个增删改查@落雨

    作为一名专业的CRUD-Boy,本篇介绍如何使用io.vavr工具包来写一个比较舒服的有则更新,无则新增CRUD小需求

    一、io.vavr

    1).Optional怎么玩?jdk8

    // 有则更新,无则新增,不推荐
    if(optional.isPresent){
        // 有则更新
        optional.get();
    } else {
        // 无则新增
    }
    

    或者

    
    optional.map(record -> {
      // 有则更新
      update(record);
    })
    // 无则新增
    .orElse(getNewRecord());
    

    2).如果不用Optional如何写?

    // 把Java的Optional转为io.vavr的Option,然后判断空和非空
    Option.ofOptional(optional).onEmpty(() -> {
        // 处理空的情况,无则新增
        insert();
    }).peek(record -> {
        // 处理非空的情况,有则更新
        update(record);
    });
    
    

    io.vavr介绍:
    https://www.vavr.io/

    用到的武器:Optional -> Option

    // optional *value*, no more nulls
    Option<T> option = Option.of(...);
    

    引入pom

     <dependency>
         <groupId>io.vavr</groupId>
         <artifactId>vavr</artifactId>
         <version>0.10.3</version>
    </dependency>
    

    二、写一个Repo

    /**
     * @author luoyu.lzy
     * @Title: AppUserRepo.java
     * @Description:
     * @date 2021/9/1.
     */
    public interface AppUserRepo {
    
        /**
         * 持久化,有则更新,无则新增
         * @param appUser
         * @return
         */
        AppUser save(AppUser appUser);
    
        /**
         * 根据id获取DTO
         * @param id
         * @return
         */
        AppUser getById(Long id);
    }
    
    

    三、实现这个Repo

    
    /**
     * @author luoyu.lzy
     * @Title:AppUserRepoImpl.java
     * @Description:用户Repo实现类
     * @date 2021/9/1.
     */
    @Component
    public class AppUserRepoImpl implements AppUserRepo {
        
        @Autowired
        private AppUserDAO appUserDAO;
        
       /**
        * 查询DB,根据id获取Record
        */
        private Optional<AppUserDO> getRecordById(Long id) {
           return Optional.ofNullable(appUserDAO.selectByPrimaryKey(id));
        }
        
        /**
        * bean转换 DO -> DTO
        */
         @Override
        public AppUser getById(Long id) {
            Optional<AppUserDO> optional = getRecordById(id);
            // toAppUser bean转换
            return optional.map(this::toAppUser).orElse(null);
        }
        
       /**
        * 保存,有则更新部分字段,无则新增
        */
        @Override
        public AppUser save(AppUser appUser) {
            Option.ofOptional(getRecordById(appUser.getId())).onEmpty(() -> {
                AppUserDO record = toAppUserDO(appUser);
                record.setGmtCreate(Calendar.getInstance().getTime());
                record.setGmtModified(Calendar.getInstance().getTime());
                int insertResult = appUserDAO.insert(record);
                if (insertResult > 0) {
                    record.setId(record.getId());
                }
            }).peek(record -> {
                record.setStatus(appUser.getStatus());
                appUserDAO.updateByPrimaryKey(record);
            });
            return appUser;
        }
    
    }
    

    四、Option.of 源码分析

    我们回到这段代码, 分别是Option.of(Optional).onEmpty().peek() 这3个api,我们来看看核心代码。

    // 把Java的Optional转为io.vavr的Option
    Option.ofOptional(xxxOptinal).onEmpty(() -> {
        // 处理空的情况
    }).peek(record -> {
        // 处理非空的情况
    });
    
    

    再来看看Option.ofOptional源码

    
        /**
         * 包裹Optional对象,返回Option对象     
         */
        @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
        static <T> Option<T> ofOptional(Optional<? extends T> optional) {
        // optional不能为null
            Objects.requireNonNull(optional, "optional is null");
            //通过java.util.Optional.map(Option.of)方法来包装optional每个元素
            return optional.<Option<T>>map(Option::of).orElseGet(Option::none);
        }
           
         static <T> Option<T> of(T value) {
            // none和same分别用来生产None对象和Same对象,None和Same代表无元素(None=无元素)和有元素(Same=相同类型的元素)
            return (value == null) ? none() : some(value);
        }
        
        /**
         * java.util.Optional
         * 通过Optional.map方法,返回Optional对象
        */
        public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
            Objects.requireNonNull(mapper);
            if (!isPresent())
                return empty();
            else {
                // 执行mapper函数
                return Optional.ofNullable(mapper.apply(value));
            }
        }
        
       /**
        * 处理OnEmpty事件,如果元素为空,则执行 Runnable.run
        */
        default Option<T> onEmpty(Runnable action) {
            Objects.requireNonNull(action, "action is null");
            if (isEmpty()) {
                action.run();
            }
            return this;
        }
        
       /**
        * 处理peek事件,如果不为empty,则执行Consumer.accept
        */
        default Option<T> peek(Consumer<? super T> action) {
            Objects.requireNonNull(action, "action is null");
            if (isDefined()) {
                action.accept(get());
            }
            return this;
        }
        
        
    

    五、整完,CRUD更简洁

    六、Optional的进化

    Java 9 Optional API 新增方法 or,可以实现类似Option.onEmpty的功能

    Optional<T> optional = Optional.empty();
    Optional<T> result = optional.or(() -> doSomeThionEmpty);
    

    落雨 http://js-dev.cn
    2021-09-13 21:13:00

  • 相关阅读:
    linux下的shell 快捷键
    Python3.x和Python2.x的区别
    [Python2.x] 利用commands模块执行Linux shell命令
    redis缓存策略
    高并发解决方案
    java8 lambda表达式应用
    java读写分离的实现
    数据库读写分离
    大数据量处理方案:分布式数据库
    google的CacheBuilder缓存
  • 原文地址:https://www.cnblogs.com/ae6623/p/15264848.html
Copyright © 2020-2023  润新知