SpringBoot 通用 MongoDao 封装

本贴最后更新于 1651 天前,其中的信息可能已经天翻地覆

MongoDao

package com.yoyo.framework.mongo;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.yoyo.framework.api.RTPaging;
import com.yoyo.framework.json.JSONUtils;
import com.yoyo.framework.reflect.ReflectUtil;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/***
 @Author:MrHuang
 @Date: 2019/9/4 16:19
 @DESC: TODO
 @VERSION: 1.0
 ***/
@Repository
public class MongoDao<K,V> {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 新增
     * @param v
     * @return
     */
    public V insert(V v) {
        return mongoTemplate.insert(v);
    }

    /**
     * 查询
     * @param id
     * @return
     */
    public V findById(K id) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        return mongoTemplate.findById(id, vClass);
    }

    /**
     * 根据ID批量查询
     * @param ids
     * @return
     */
    public List<V> findByIds(List<K> ids) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        String idFieldName = ReflectUtil.getFieldName(vClass, Id.class);
        Assert.notNull(idFieldName, "@Id not find");
        return mongoTemplate.find(Query.query(Criteria.where(idFieldName).in(ids)), vClass);
    }

    /**
     * 强制更新
     * @param v
     * @return
     */
    public UpdateResult updateById(V v) {
        Update update = Update.fromDocument(Document.parse(JSONUtils.object2Json(v)));
        ReflectUtil.FieldNameValue id = ReflectUtil.getFieldNameValue(v, Id.class);
        Assert.notNull(id, "@Id not find");
        return mongoTemplate.updateFirst(Query.query(Criteria.where(id.getFieldName()).is(id.getFieldValue())), update, v.getClass());
    }

    /**
     * 乐观锁更新
     * @param v
     * @return
     */
    public UpdateResult updateByIdWithVersion(V v) {
        ReflectUtil.FieldNameValue id = ReflectUtil.getFieldNameValue(v, Id.class);
        Assert.notNull(id, "@Id not find");
        ReflectUtil.FieldNameValue version = ReflectUtil.getFieldNameValue(v, MongoVersion.class);
        Assert.notNull(version, "@MongoVersion not find");
        Object fieldValue = Optional.ofNullable(version.getFieldValue()).orElse("0");
        Criteria criteria = Criteria.where(id.getFieldName()).is(id.getFieldValue()).and(version.getFieldName()).is(fieldValue);
        // 版本号+1
        ReflectUtil.setFieldValue(v, version.getFieldName(), (Integer.parseInt(fieldValue.toString()) + 1) + "");
        Update update = Update.fromDocument(Document.parse(JSONUtils.object2Json(v)));
        update.set("_class", v.getClass().getName());
        return mongoTemplate.updateFirst(Query.query(criteria), update, v.getClass());
    }

    /**
     * 物理删除
     * @param id
     * @return
     */
    public DeleteResult deleteById(K id) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        String idFieldName = ReflectUtil.getFieldName(vClass, Id.class);
        Assert.notNull(idFieldName, "@Id not find");
        return mongoTemplate.remove(Query.query(Criteria.where(idFieldName).is(id)), vClass);
    }


    /**
     * 根据查询条件查找列表
     * @param criteria
     * @return
     */
    public List<V> find(Criteria criteria) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        return mongoTemplate.find(Query.query(criteria), vClass);
    }

    /**
     * 根据查询条件查找列表
     * @param criteria
     * @return
     */
    public List<V> find(Criteria criteria, Sort sort, Long skip, Integer limit) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        Query query = Query.query(criteria);
        if (Objects.nonNull(sort)) {
            query.with(sort);
        }
        if (Objects.nonNull(skip)) {
            query.skip(skip);
        }
        if (Objects.nonNull(limit)) {
            query.limit(limit);
        }
        return mongoTemplate.find(query, vClass);
    }

    /**
     * 根据查询条件查找条数
     * @param criteria
     * @return
     */
    public long count(Criteria criteria) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        return mongoTemplate.count(Query.query(criteria), vClass);
    }


    /**
     * 根据查询条件分页查询
     * @param criteria 查询条件
     * @param sort 排序条件
     * @param pageNow 查找的页数
     * @param pageSize 每页显示大小
     */
    public RTPaging<V> paging(Criteria criteria, Sort sort, long pageNow, int pageSize) {
        long totalRecord = this.count(criteria);
        long totalPage = RTPaging.getTotalPage(totalRecord, pageSize);
        long skip = RTPaging.getSkip(pageNow, pageSize);
        List<V> recond = this.find(criteria, sort, skip, pageSize);
        return new RTPaging<V>().setPageNow(pageNow).setPageSize(pageSize)
                .setTotalRecord(totalRecord).setTotalPage(totalPage)
                .setRecord(recond);
    }


    /**
     * 更新第一条匹配到的
     * @param criteria
     * @param update
     * @return
     */
    public UpdateResult updateFirst(Criteria criteria, Update update) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        return mongoTemplate.updateFirst(Query.query(criteria), update, vClass);
    }

    /**
     * 更新所有匹配到的
     * @param criteria
     * @param update
     * @return
     */
    public UpdateResult updateMulti(Criteria criteria, Update update) {
        Class<V> vClass = (Class<V>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        return mongoTemplate.updateMulti(Query.query(criteria), update, vClass);
    }
}

ReflectUtil

package com.yoyo.framework.reflect;

import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/***
 @Author:MrHuang
 @Date: 2019/9/4 16:42
 @DESC: TODO
 @VERSION: 1.0
 ***/
@Slf4j
public class ReflectUtil {

    /**
     * 根据注解获取Field
     * @param clazz
     * @param annotationCls
     * @return
     */
    public static Field getField(Class<?> clazz,  Class<? extends Annotation> annotationCls) {
        List<Field> list = FieldUtils.getFieldsListWithAnnotation(clazz, annotationCls);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据注解获取FieldValue
     * @param object
     * @param annotationCls
     * @return
     */
    public static Object getFieldValue(Object object, Class<? extends Annotation> annotationCls)  {
        return Optional.ofNullable(getFieldNameValue(object, annotationCls)).map(FieldNameValue::getFieldValue).orElse(null);
    }

    /**
     * 根据注解获取FieldName
     * @param object
     * @param annotationCls
     * @return
     */
    public static String getFieldName(Object object, Class<? extends Annotation> annotationCls) {
        return Optional.ofNullable(getFieldNameValue(object, annotationCls)).map(FieldNameValue::getFieldName).orElse(null);
    }

    public static String getFieldName(Class objectClass, Class<? extends Annotation> annotationCls) {
        Field field = ReflectUtil.getField(objectClass, annotationCls);
        return Objects.nonNull(field) ? field.getName() : null;
    }

    /**
     * 根据注解获取FieldNameValue
     * @param object
     * @param annotationCls
     * @return
     */
    public static FieldNameValue getFieldNameValue(Object object, Class<? extends Annotation> annotationCls) {
        if (Objects.isNull(object) || Objects.isNull(annotationCls)) {
            return null;
        }
        Field field = ReflectUtil.getField(object.getClass(), annotationCls);
        if (Objects.nonNull(field)) {
            field.setAccessible(true);
            try {
                return new FieldNameValue().setFieldName(field.getName()).setFieldValue(field.get(object));
            } catch (IllegalAccessException e) {
                log.error("ReflectUtil getFieldNameValue error", e);
            }
        }
        return null;
    }

    /**
     * 根据注解获取FieldNameValue
     * @param object
     * @param fieldName
     * @param newFieldValue
     * @return
     */
    public static void setFieldValue(Object object, String fieldName, Object newFieldValue) {
        Field field = FieldUtils.getField(object.getClass(), fieldName, true);
        try {
            field.set(object, newFieldValue);
        } catch (IllegalAccessException e) {
            log.error("ReflectUtil setFieldValue error", e);
        }
    }

    @Data
    @Accessors(chain = true)
    public static class FieldNameValue implements Serializable {
        private String fieldName;

        private Object fieldValue;
    }
}

RoleDTO

package com.yoyo.authority.role.pojo.dto;

import com.yoyo.framework.mongo.MongoVersion;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

/***
 @Author:MrHuang
 @Date: 2019/9/4 10:48
 @DESC: TODO
 @VERSION: 1.0
 ***/
@Data
@Accessors(chain = true)
@Document(collection = "t_role")
public class RoleDTO implements Serializable {

    @Id
    private String rid;

    @Field
    private String name;

    @Field
    private String remark;

    @Field
    private Integer roleStatus;

    @Field
    private List<String> bindMenuId;

    @Field
    private String createTime;

    @Field
    private String updateTime;

    @MongoVersion
    private String version;
}

MongoVersion

package com.yoyo.framework.mongo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/***
 @Author:MrHuang
 @Date: 2019/9/5 15:02
 @DESC: TODO 乐观锁版本
 @VERSION: 1.0
 ***/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MongoVersion {
}

RoleDao

package com.yoyo.authority.role.dao;

import com.yoyo.authority.role.pojo.dto.RoleDTO;
import com.yoyo.framework.mongo.MongoDao;
import org.springframework.stereotype.Repository;

/***
 @Author:MrHuang
 @Date: 2019/9/5 16:54
 @DESC: TODO
 @VERSION: 1.0
 ***/
@Repository
public class RoleDao extends MongoDao<String, RoleDTO> {
}

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    938 引用 • 1456 回帖 • 163 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...