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数据库操作自定义接口的封装和使用