spring data mongo使用笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufang1991/article/details/78915127

先列提纲,后续有时间再完善

1.配置

maven依赖

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

如果使用默认的配置一行搞定, 如果用户名和密码中有:和@符号,需要进行urlencode,@用%40替换,假如密码是123@admin,那么就要写成123%40admin,源码中在设置用户名和密码的时候根据:和@符号进行劈分,然后URLDecoder.decode(input, "UTF-8")

spring.data.mongodb.uri=mongodb://admin:[email protected]:27017/admin

多数据源

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class, MongoDataAutoConfiguration.class})
mongod.user.uri=mongodb://admin:[email protected]:27017/admin
mongod.article.uri=mongodb://admin:[email protected]:27017/article
@Configuration
@ConfigurationProperties(prefix="mongod.user")
@EnableMongoRepositories(basePackages={"com.**.repository.user"},mongoTemplateRef = "mongoUserTemplate")
public class MongoUserConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(MongoUserConfig.class);

    private String uri;

    public MongoDbFactory simpleFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClientURI(uri));
    }

    @Bean(name="mongoUserTemplate")
    public MongoTemplate mongoUserTemplate() throws Exception {
        LOGGER.info("init mongodb template uri={}", uri);
        return new MongoTemplate(simpleFactory());
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }
}
@Data
@Configuration
@ConfigurationProperties(prefix="mongod.content")
@EnableMongoRepositories(basePackages={"com.**.repository.content"},mongoTemplateRef = "mongoContentTemplate")
public class MongoUserConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(MongoUserConfig.class);

    private String uri;

    public MongoDbFactory simpleFactory() throws Exception {
	   SimpleMongoDbFactory factory = new SimpleMongoDbFactory(new MongoClientURI(uri));
       factory.setWriteConcern(WriteConcern.MAJORITY.withJournal(true));
       return factory;
    }

    @Bean(name="mongoContentTemplate")
    public MongoTemplate mongoContentTemplate() throws Exception {
        LOGGER.info("init mongodb template uri={}", uri);
        return new MongoTemplate(simpleFactory());
    }
}

2.注解

import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Version;

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

@Data
public abstract class DocBase {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected String id;

    @Version
    protected Long version;

    @CreatedDate
    protected Date createdDate;

    @LastModifiedDate
    protected Date lastModifiedDate;

}
@Data
@Document(collection = "article")
@CompoundIndexes({
        @CompoundIndex(name = "article_revision_idx", def = "{ 'id' : 1, 'revision': -1}", unique = true)
})
public class Article extends DocBase{
    @Indexed
    private String userId;
	private int revision;
	private String content;
	private String articleId;
	@DBRef
	@NotNull
	private List<Attachment> attachments = Collections.emptyList();
	@Transient
    private boolean hasModifiled;
}

@Indexed 单一索引

@CompoundIndexes 符合索引

@DBRef 外部集合文档引用,官方说如果引用不多的话建议还是自己存一个另外一个集合文档的ID,多一次查询

@Transient 字段不入库,做为处理的中间字段

3.MongoRepository查询和mongoTemplate

repository可以指定返回部分字段

@Query(query="?1",fields="?2")  List<Result> findPart(Map<Object,Object> query,Map<String,Integer> fileds)

new Query(Criteria)

new BasicQuery(DBObject,DBObject),第二个参数可以指定返回的字段

QueryBuilder没有用过

        List<String> articleIds = Arrays.asList<>("1","2");
		List<String> fields = Arrays.asList<>("aricleId","content");
		Criteria c = Criteria.where("articleType").is("news").and("revision").is(1).and("articleId").in(articleIds);
        DBObject fieldsDB = new BasicDBObject();
        fields.forEach(s->fieldsDB.put(s,true));
        Query query = new BasicQuery(c.getCriteriaObject(),fieldsDB);
        return mongoTemplate.find(query, Question.class, collectionName);

分页排序查询,注意页码是从1开始,即第1页的pageSize = 1

 Pageable pageable = new PageRequest(1, 10, new Sort(Sort.Direction.DESC, "lastModifiedDate"));

原子更新操作

mongoTemplate.updateFirst(new Query(where("id").is(counter.getId())), new Update().inc("data." + key, 1), Counter.class);

4.Convert

这里只是记录一下可以改变插入的数据,和读出的数据

public class MongoDBConfig extends AbstractMongoConfiguration {
    @Bean
    @Override
    public CustomConversions customConversions() {
        List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
        converterList.add(new TreeReadConverter());
        converterList.add(new TreeWriteConverter());
        return new CustomConversions(converterList);
    }
}
@ReadingConverter
public class TreeReadConverter implements Converter<DBObject, Tree<?>> {
    private static final Logger LOG = LoggerFactory.getLogger(TreeReadConverter.class);
    @Override
    public Tree<?> convert(DBObject source) {
       //TODO 读出来的时候可以自己对数据进行加工处理
	   return null;
    }
}
@WritingConverter
public class TreeWriteConverter implements Converter<Tree<?>, DBObject> {
    private static final Logger LOG = LoggerFactory.getLogger(TreeWriteConverter.class);
    @Override
    public DBObject convert(Tree<?> source) {
	    // TODO 在保存数据的时候可以自己对数据对象进行变更
        return null;
    }
}

5. MongoRepository实现自定义接口

在 repositoryImpl中利用mongoTemplate实现自定义接口的方法,会自动扫描后缀Impl的类

interface IArticleHistory {
    Article insertToHistory(Article article);
}
public interface ArticleRepository extends MongoRepository<Question, String>, IArticleHistory {
}
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

class ArticleRepositoryImpl implements IArticleHistory {

    private String collectionName = "articleHistory";

    @Inject
    private MongoTemplate mongoTemplate;

    @PostConstruct
    void createReleaseCollection() {
        DBObject indexKeys = BasicDBObjectBuilder.start("articleId", 1)
                .add("reVision", -1)
                .get();
        DBObject indexOptions = BasicDBObjectBuilder.start("unique", true).get();
        BasicDBObjectBuilder.start("keys", indexKeys).add("options", indexOptions).get();
        mongoTemplate.getCollection(collectionName).createIndex(indexKeys, indexOptions);
    }

    @Override
    public Article insertToHistory(Article article) {
        article.setId(null);
        mongoTemplate.insert(article, collectionName);
        return article;
    }
}

6.备注

mongo会自动去除空字符串或者null的字段

mongodb默认的排序有一个32M内存大小限制,可以通过对排序字段增加索引或者增大32M的限制来解决,但是建议在Java层去做排序

猜你喜欢

转载自blog.csdn.net/liufang1991/article/details/78915127