最近使用了最新本版’spring-boot-starter-data-mongodb’, version: ‘2.2.6.RELEASE’和’mongo-java-driver’, version: '3.12.3’在使用上有了些许改动。
最重要的就是DB类的弃用:
MongoTemplate:
public MongoDatabase getDb() {
return doGetDatabase();
}
MongoDbFactory:
MongoDatabase getDb() throws DataAccessException;
MongoClient:
public MongoDatabase getDatabase(final String databaseName) {
......
}
MongoTemplate与MongoDbFactory中的getDb方法返回值都由之前的DB类型改为了MongoDatabase ,但是列入GridFs的构造方法传入参数还是DB并没有改为MongoDatabase 类型,这就直接导致我们之前很多使用到DB的地方现在不能直接使用了。
public GridFS(final DB db) {
this(db, DEFAULT_BUCKET);
}
/**
* Creates a GridFS instance for the specified bucket in the given database. Set the preferred WriteConcern on the give DB with
* DB.setWriteConcern
*
* @param db database to work with
* @param bucket bucket to use in the given database
* @throws com.mongodb.MongoException if there's a failure
* @see com.mongodb.WriteConcern
*/
public GridFS(final DB db, final String bucket) {
this.database = db;
this.bucketName = bucket;
this.filesCollection = database.getCollection(bucketName + ".files");
this.chunksCollection = database.getCollection(bucketName + ".chunks");
// ensure standard indexes as long as collections are small
try {
if (filesCollection.count() < 1000) {
filesCollection.createIndex(new BasicDBObject("filename", 1).append("uploadDate", 1));
}
if (chunksCollection.count() < 1000) {
chunksCollection.createIndex(new BasicDBObject("files_id", 1).append("n", 1),
new BasicDBObject("unique", true));
}
} catch (MongoException e) {
//TODO: Logging
}
filesCollection.setObjectClass(GridFSDBFile.class);
}
例如我们之前的操作方式现在完全是行不通的:
/**
* 据id返回文件
*/
public GridFSDBFile getById(ObjectId id){
GridFS gridFS = new GridFS(mongodbfactory.getDb()); // 这里会无法进行类型转换
return gridFS.findOne(new BasicDBObject("_id", id));
}
看注释发现可能是目前的遗留问题,还没有完全迁移过来。如果不适应可以退回旧的稳定版本等日后稳定了再用新版本。下面提供下我自己在新本中使用的方式:
首先可以看到GridFS类中定义了默认的存储桶,如果我们不手动指定,查询和插入就都会指向这个默认创建的桶中。我们可以在配置类中手动配置自己想操作的存储桶:
/**
* @author haichi
* @version 1.0
* @date 2020/4/11 23:27
*/
@Configuration
public class MongoConfig {
@Autowired
MongoDbFactory mongoDbFactory;
// //获取yml文件中的连接数据库
// @Value("${spring.data.mongodb.database}")
String db = "filedb";
@Bean
public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory, MongoConverter converter) {
return new GridFsTemplate(mongoDbFactory, converter, "files");
}
//GridFSBucket用于打开下载流对象
@Bean
public GridFSBucket getGridFSBucket(MongoClient mongoClient){
MongoDatabase database =mongoDbFactory.getDb();
System.out.println(database.getName());
GridFSBucket bucket = GridFSBuckets.create(database,"files");
return bucket;
}
}
存入:
public ObjectId save(File file){
try(InputStream inputStream = new FileInputStream(file);){
ObjectId objectId = gridFsTemplate.store(inputStream,file.getName());
return objectId;
}
catch (Exception e){
log.error("文件写入mongo失败:" + e.getMessage());
e.printStackTrace();
}
return null;
}
我这里是测试用例实际生产中可以把File换为MultipartFile类型。try()这种写法可以自动关闭流。
取出文件:
public GridFSFile getById(ObjectId id) throws IOException {
Query query = Query.query(Criteria.where("_id").is(id));
GridFSFile gridFSFile = gridFsTemplate.findOne(query);
return gridFSFile;
}
后续:
GridFsResource resource = new GridFsResource(gridFSFile);
GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getId());
//创建gridFsResource,用于获取流对象
GridFsResource resource = new GridFsResource(gridFSFile,gridFSDownloadStream);
InputStream inputStream = resource.getInputStream();
拿到输入流就可以自行操作了