spring boot 整合spring-data-mongodb自定义接口扩展

spring boot 整合spring-data-mongodb自定义接口扩展

  • 这里使用的依然是SpringBoot 1.5.9.RELEASE和JDK1.8

1、添加Maven依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2、添加数据源配置

application.yml

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: test
      username: admin
      password: admin

3、创建公共Base接口

公共接口声明BaseMongoRepository.java

package com.lilian.base.mongo;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;

/**
 * jpa-demo
 * 在此类中添加自定义的方法
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
@NoRepositoryBean
public interface BaseMongoRepository<T, ID extends Serializable>
        extends MongoRepository<T, ID> {

    /**
     * 自定义分页查询
     *
     * @param query
     * @param pageable
     * @return
     */
    Page<T> findPageByQuery(Query query, Pageable pageable);

    /**
     * 自定义分页查询
     *
     * @param criteria
     * @param pageable
     * @return
     */
    Page<T> findPageByCriteria(Criteria criteria, Pageable pageable);
}
  • 需要添加@NoRepositoryBean注解来说明此接口不是一个声明的Repository,否则Spring默认当做普通的Repository来处理;
  • 可以在此接口中生命一些自定义的接口公共方法;
    公共接口实现类SimpleBaseMongoRepository
package com.lilian.base.mongo;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;

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

/**
 * jpa-demo
 * 自定义接口中方法的实现
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
public class SimpleBaseMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements BaseMongoRepository<T, ID> {

    private final MongoOperations mongoOperations;

    private final MongoEntityInformation<T, ID> entityInformation;

    public SimpleBaseMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
        super(metadata, mongoOperations);
        this.mongoOperations = mongoOperations;
        this.entityInformation = metadata;
    }

    protected Class<T> getEntityClass() {
        return entityInformation.getJavaType();
    }

    @Override
    public Page<T> findPageByQuery(Query query, Pageable pageable) {
        long total = mongoOperations.count(query, getEntityClass());
        List<T> list = mongoOperations.find(query.with(pageable), getEntityClass());

        return new PageImpl<T>(list, pageable, total);
    }

    @Override
    public Page<T> findPageByCriteria(Criteria criteria, Pageable pageable) {
        return findPageByQuery(new Query(criteria), pageable);
    }
}

4、重写MongoRepositoryFactoryBean中的方法

BaseMongoRepositoryFactoryBean.java

package com.lilian.base.mongo;

import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.data.mongodb.repository.support.QueryDslMongoRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import java.io.Serializable;

import static org.springframework.data.querydsl.QueryDslUtils.QUERY_DSL_PRESENT;

/**
 * jpa-demo
 *
 * @Author 孙龙
 * @Date 2018/7/10
 */
public class BaseMongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID extends Serializable>
        extends MongoRepositoryFactoryBean<T, S, ID> {

    public BaseMongoRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
        return super.getFactoryInstance(operations);
    }

    private static class LCRRepositoryFactory<S, ID extends Serializable> extends MongoRepositoryFactory {

        private final MongoOperations mongoOperations;

        public LCRRepositoryFactory(MongoOperations mongoOperations) {
            super(mongoOperations);
            this.mongoOperations = mongoOperations;
        }

        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            Class<?> repositoryInterface = information.getRepositoryInterface();
            MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
            if (isQueryDslRepository(repositoryInterface)) {
                return new QueryDslMongoRepository(entityInformation, mongoOperations);
            } else {
                return new SimpleBaseMongoRepository<S, ID>((MongoEntityInformation<S, ID>) entityInformation, this.mongoOperations);
            }
        }


        private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
            return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return isQueryDslRepository(metadata.getRepositoryInterface()) ? QueryDslMongoRepository.class
                    : SimpleBaseMongoRepository.class;
        }
    }
}

5、覆盖SpringBoot提供的默认配置

MongoRepositoryConfig.java

package com.lilian.base;

import com.lilian.base.mongo.BaseMongoRepositoryFactoryBean;
import com.lilian.base.mongo.SimpleBaseMongoRepository;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

/**
 * jpa-demo
 * 自定义jpa配置类
 *
 * @Author 孙龙
 * @Date 2018/7/2
 */
@Configuration
@EnableMongoRepositories(repositoryBaseClass = SimpleBaseMongoRepository.class, basePackages = {"com.lilian.repository.mongo"}, repositoryFactoryBeanClass = BaseMongoRepositoryFactoryBean.class)
public class MongoRepositoryConfig {
}
  • basePackages参数指定的是普通Repository所在的路径,可以指定多个

6、使用Base接口开发

(1)创建实体类

Student.java

package com.lilian.entity.mongo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Id;
import java.util.Date;

/**
 * jpa-demo
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {

    @Id
    private String id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 地址
     */
    private String addr;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 添加时间
     */
    private Date addTime;
    /**
     * 手机号
     */
    private String phoneNum;

}

(2)创建Repository

StudentRepository.java

package com.lilian.repository.mongo;

import com.lilian.base.mongo.BaseMongoRepository;
import com.lilian.entity.mongo.Student;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

/**
* jpa-demo
*
* @Author 孙龙
* @Date 2018/7/9
*/
public interface StudentRepository extends BaseMongoRepository<Student, String> {
   /**
    * 根据地址查询所有
    *
    * @param addr
    * @return
    */
   List<Student> findAllByAddr(String addr);

   /**
    * 根据实体类中的属性进行模糊查询
    *
    * @param name
    * @return
    */
   List<Student> findByNameLike(String name);

   /**
    * 根据实体类中的属性进行模糊查询带分页
    * 带分页的模糊查询,其实是把模糊查询以及分页进行合并,
    * 定义方法名的规则和模糊查询的规则一致,只是参数不同而已。
    *
    * @param name
    * @param pageable
    * @return
    */
   Page<Student> findByNameLike(String name, Pageable pageable);

   /**
    * 查询年龄小于某值的所有数据
    *
    * @param maxAge
    * @return
    */
//    @Query("")
   List<Student> findAllByAgeLessThan(int maxAge);
}

(3)Service层

IStudentService.java

package com.lilian.service.mongo;

import com.lilian.entity.mongo.Student;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * jpa-demo
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
public interface IStudentService {
    /**
     * 查询全部(自带)
     *
     * @return
     */
    List<Student> queryAll();

    /**
     * 批量插入(自带)
     */
    void batchSave(List<Student> studentList);

    /**
     * 根据地址查询全部(名称拼接方式)
     *
     * @param address
     * @return
     */
    List<Student> queryAllByAddr(String address);

    /**
     * 根据实体类中的属性进行模糊查询
     *
     * @param name
     * @return
     */
    List<Student> queryByNameLike(String name);

    /**
     * 模糊查询加分页
     *
     * @param page
     * @param rows
     * @param name
     * @return
     */
    Page<Student> queryByNameAndPage(int page, int rows, String name);

    /**
     * 根据最大年龄查询所有学生
     *
     * @param age
     * @return
     */
    List<Student> queryAllByAgeLessThan(int age);

    /**
     * 根据年龄范围查询全部(Example查询方式)
     *
     * @param student
     * @return
     */
    List<Student> queryByVo(Student student);
}

StudentServiceImpl.java

package com.lilian.service.mongo.impl;

import com.lilian.entity.mongo.Student;
import com.lilian.repository.mongo.StudentRepository;
import com.lilian.service.mongo.IStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * jpa-demo
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
@Service
public class StudentServiceImpl implements IStudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public List<Student> queryAll() {

        return studentRepository.findAll();
    }

    @Override
    public void batchSave(List<Student> studentList) {
        studentRepository.insert(studentList);
    }

    @Override
    public List<Student> queryAllByAddr(String address) {
        return studentRepository.findAllByAddr(address);
    }

    @Override
    public List<Student> queryByNameLike(String name) {
        return studentRepository.findByNameLike(name);
    }

    @Override
    public Page<Student> queryByNameAndPage(int page, int rows, String name) {
        PageRequest pageRequest = new PageRequest(page, rows);
        return studentRepository.findByNameLike(name, pageRequest);
    }

    @Override
    public List<Student> queryAllByAgeLessThan(int age) {
        return studentRepository.findAllByAgeLessThan(age);
    }

    @Override
    public List<Student> queryByVo(Student student) {

        Example<Student> example = Example.of(student);

        return studentRepository.findAll(example);
    }
}

7、测试类

StudentServiceImplTest.java

package com.lilian.service.mongo.impl;

import com.lilian.entity.mongo.Student;
import com.lilian.service.mongo.IStudentService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * jpa-demo
 *
 * @Author 孙龙
 * @Date 2018/7/9
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class StudentServiceImplTest {

    @Autowired
    private IStudentService studentService;

    @Test
    public void queryAll() {

        List<Student> studentList = studentService.queryAll();
        for (Student student : studentList) {
            System.out.println(student);
        }
    }

    @Test
    public void batchSave() {
        List<Student> studentList = new ArrayList<Student>() {{
            add(new Student("dsrfj3frs", "马云", 35, "杭州", "master@alibaba.com", new Date(System.currentTimeMillis() - 10000L), "186666666"));
            add(new Student("gfrgtr54d", "周鸿祎", 25, "北京", "master@360.com", new Date(System.currentTimeMillis() - 20000L), "1822222222"));
            add(new Student("iuti7thty", "马化腾", 40, "深圳", "master@qq.com", new Date(System.currentTimeMillis() - 30000L), "183333333"));
            add(new Student("vchfgdher", "丁磊", 25, "杭州", "master@163.com", new Date(System.currentTimeMillis() - 40000L), "1844444444"));
        }};
        studentService.batchSave(studentList);
    }

    @Test
    public void queryAllByAddr() {
        String address = "杭州";
        List<Student> studentList = studentService.queryAllByAddr(address);
        for (Student student : studentList) {
            System.out.println(student);
        }

    }

    @Test
    public void queryByNameLike() {
        String name = "马";
        List<Student> studentList = studentService.queryByNameLike(name);
        for (Student student : studentList) {
            System.out.println(student);
        }
    }

    @Test
    public void queryByNameAndPage() {
        String name = "马";
        Page<Student> studentPage = studentService.queryByNameAndPage(0, 10, name);
        System.out.println("总条数" + studentPage.getTotalElements());
        System.out.println("总页数" + studentPage.getTotalPages());
        //数据列表
        List<Student> studentList = studentPage.getContent();
        for (Student student : studentList) {
            System.out.println(student);
        }
    }

    @Test
    public void queryAllByAgeLessThan() {
        int age = 35;
        List<Student> studentList = studentService.queryAllByAgeLessThan(age);
        for (Student student : studentList) {
            System.out.println(student);
        }

    }

    @Test
    public void queryByVo() {
        Student student = new Student(null, null, 25, "杭州", null, null, null);
        List<Student> studentList = studentService.queryByVo(student);
        for (Student student1 : studentList) {
            System.out.println(student1);
        }
    }
}

github代码示例
示例中包含Spring data jpa对Mysql数据库操作自定义接口的封装和使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,678评论 6 342
  • spring boot整合Spring-data-jpa自定义扩展接口 基于Spring boot1.5.9.RE...
    搁浅_Jay阅读 4,073评论 0 6
  • 运动起来大汗淋漓,思路也变得开阔了,所有烦心事都成了过眼云烟 今天心情不好,就狠狠地宰了朋友一顿,骑车看电影吃大餐...
    不能没有阅读 463评论 0 3
  • 路啊都是很长很长 远远的看不到头 赶路的人呵 你有一个目的 你要去哪儿? 你想去哪儿? 你打算如何去? 走着、爬着...
    天空鲸阅读 120评论 0 3