您的位置:首页 > 编程语言 > Java开发

[SpringBoot实践]spring-data-mongo自定义Repository接口及其实现

2016-04-14 21:45 746 查看

概述

通常我们使用spring-data-mongo时,会让我们的Repository(如UserRepository)继承MongoRepository接口,然后编写业务方法。碰到需要自定义实现代码的时候,就编写UserRepositoryImpl类。不管如何都是非常方便的。

但是有时候的一些方法是需要通用的,比如通过Criteria进行查询(MongoRepository没有相关的方法提供。可能是小弟没有发现,有误的话希望大家可以指出^-^)。

不多说,开始搬砖。

创建项目

说明

这里直接用Spring-boot快速创建项目,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>dpos-repository</artifactId>

<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

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


然后我们定义实体类User

@Document
public class User extends BaseEntity{
private String name;
private String password;
//各种setter,getter
}


方案一

编写Repository接口

public interface UserRepository extends MongoRepository<User, String> {

/**
*
* @param criteria
* @param pageable
* @return
*/
Page<User> find(Criteria criteria, Pageable pageable);
}


然后编写实现类UserRepositoryImpl

public class UserRepositoryImpl{

@Autowired
protected MongoTemplate mongoTemplate;

/**
* @param criteria
* @param pageable
* @return
*/
Page<User> find(Criteria criteria, Pageable pageable){
Query query=new Query(criteria);
final long total=mongoTemplate.count(query, User.class);
final List<User> list=mongoTemplate.find(query.with(pageable), User.class);

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


最后写一个测试用例看看我们的代码是否正确

public class UserRepoTest extends TestOnSpring{

protected final String password="123456";
final String[] names=new String[]{"张三","李四"};

protected Pageable pageable=new PageRequest(0,10);

protected static Logger logger= LoggerFactory.getLogger(UserRepoTest.class);

@Autowired
private UserRepository userRepo;

/**
* 插入数据
*/
@Before
public void init(){
inserTestData();
}

private void inserTestData(){

for(String n:names){
User u=new User();
u.setName(n).setPassword(password);
userRepo.save(u);

logger.info("插入用户:{}",u.toString());
}
}

@Test
public void select(){
List<User> users=userRepo.findAll();
assertThat(users.size(), is(2));

assertThat(users.get(0).getPassword(), is(password));
assertThat(users.get(0).getName(), is(names[0]));
}

@Test
public void findByCriteria(){
Page<User> page=userRepo.find(Criteria.where("password").is(password), pageable);

assertThat(page.getTotalElements(), is(2L));

page = userRepo.find(Criteria.where("name").is(names[0]),pageable);
assertThat(page.getTotalElements(), is(1L));
assertThat(page.getContent().get(0).getName(), is(names[0]));
}

@After
public void clear(){
logger.info("清空全部的测试数据......");
userRepo.deleteAll();
}
}


运行结果:



定义统一接口

现在我想让find(Criteria criteria,Pageable pageable)作为一个统一的方法,即有新的实体需要操作时不需要重复实现。

首先,定义我们的CommonRepository(因为项目是用scala编写,这里贴出来的是scala的实现)

/**
* 通用的Repository
* Created by zengxm on 2016/4/14 0014.
*/
@NoRepositoryBean
trait CommonRepository[T,ID<:java.io.Serializable] extends MongoRepository[T,ID]{
def find(query:Query, p: Pageable):Page[T]
def find(criteria: Criteria, p: Pageable):Page[T]
}


注意,要加上@NoRepositoryBean 注解,避免spring扫描CommonRepository。

然后编写实现类

class CommonRepositoryImpl[T, ID<:java.io.Serializable](matedata:MongoEntityInformation[T,ID],mongoOp:MongoOperations)
extends SimpleMongoRepository[T,ID](matedata, mongoOp)
with CommonRepository[T,ID]
{

override def find(query: Query, p: Pageable): Page[T] = {
val total=mongoOp.count(query, matedata.getJavaType)
val list=mongoOp.find(query.`with`(p), matedata.getJavaType)

new PageImpl[T](list, p, total)
}

override def find(criteria: Criteria, p: Pageable): Page[T] = find(new Query(criteria), p)
}


附上java版本的实现代码:

public class CommonMongoRepositoryImpl<T, ID extends Serializable> extends SimpleMongoRepository<T,ID> implements CommonRepository<T,ID> {
protected final MongoOperations mongoTemplate;

protected final MongoEntityInformation<T, ID> entityInformation;

public CommonMongoRepositoryImpl(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
super(metadata, mongoOperations);

this.mongoTemplate=mongoOperations;
this.entityInformation = metadata;
}

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

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

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

@Override
public Page<T> find(Criteria criteria, Pageable p) {
return find(new Query(criteria), p);
}
}


最后我们需要告诉Spring使用CommonRepositoryImpl作为默认的Repository实现类。

/**
* 配置默认的Repository实现类为CommonRepositoryImpl,代替SimpleMongoRepository
*
* 同时修改默认的Repository扫描目录为 com.test
* Created by zengxm on 2016/4/14 0014.
*/
@Configuration
@EnableMongoRepositories(repositoryBaseClass = classOf[CommonRepositoryImpl[_, _]], basePackages = Array("com.test"))
class Config {
}


然后UserRepository就可以继承CommonRepository了。

重新运行测试用例,结果与方案一一致。至此,功能OK。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息