spring data mongo使用筆記
先列提綱,後續有時間再完善
1.配置
maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
如果使用預設的配置一行搞定, 如果使用者名稱和密碼中有:和@符號,需要進行urlencode,@用%40替換,假如密碼是
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層去做排序