Spring 模板类的一个共同设计特点是,所有的功能都被路由到模板的一个 execute() 回调方法中。这样做有助于确保异常和任何可能需要的资源管理都得到一致执行。虽然 JDBC 和 JMS 比 MongoDB 更需要这个功能,但它仍然提供了一个发生异常转换和记录的单一地点。因此,使用这些 execute() 回调是访问 MongoDB 驱动程序的 MongoDatabase 和 MongoCollection 对象的首选方式,以执行 MongoTemplate 上没有暴露为方法的不常见操作。
以下描述了 execute() 回调方法:
<T> T execute (Class<?> entityClass, CollectionCallback<T> action) 为指定类别的实体集合运行给定的 CollectionCallback。
<T> T execute (String collectionName, CollectionCallback<T> action) 在给定名称的集合上运行给定的 CollectionCallback。
<T> T execute (DbCallback<T> action) 运行一个 DbCallback,必要时转换任何异常。Spring Data MongoDB 为 2.2 版本中引入 MongoDB 的聚合框架提供支持。
<T> T execute (String collectionName, DbCallback<T> action) 在给定名称的集合上运行一个 DbCallback,必要时转换任何异常。
<T> T executeInSession (DbCallback<T> action) 在与数据库的同一连接中运行给定的 DbCallback,以确保在写入密集型环境中的一致性,在该环境中,您可以读取所写入的数据。
下面的例子使用 CollectionCallback 来返回关于一个索引的信息:
boolean hasIndex = template.execute("geolocation", new CollectionCallback<Boolean>() {
public Boolean doInCollection(Venue.class, DBCollection collection) throws MongoException, DataAccessException {
List<Document> indexes = collection.getIndexInfo();
for (Document document : indexes) {
if ("location_2d".equals(document.get("name"))) {
return true;
}
}
return false;
}
});(1)application.properties 配置文件
# Log logging.level.root=debug # MongoDB spring.data.mongodb.uri=mongodb://localhost:27017/test
(2)AppConfig.java 配置类,配置 MongoTemplate 对象
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
/**
* 配置 MongoTemplate
* @author hxstrive.com 2022/12/23
*/
@Slf4j
@Configuration
public class AppConfig {
@Bean
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
log.info("mongoTemplate({}, {})", mongoDatabaseFactory);
return new MongoTemplate(mongoDatabaseFactory);
}
}(3)集合 person 对应的实体
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
@Builder
public class Person {
/** 用户ID */
private int id;
/** 用户姓名 */
private String name;
/** 年龄 */
private int age;
}(4)客户端代码,说明见注释。
import com.hxstrive.springdata.mongodb.entity.Person;
import com.mongodb.MongoException;
import com.mongodb.client.ListIndexesIterable;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.TextIndexDefinition;
@SpringBootTest
class ListenerDemo1 {
@Autowired
private MongoTemplate mongoTemplate;
@BeforeEach
public void init() {
mongoTemplate.dropCollection(Person.class);
}
@Test
void creatIndex() {
// 判断指定的 Index 是否存在
boolean hasIndex = mongoTemplate.execute(Person.class, new CollectionCallback<Boolean>() {
@Override
public Boolean doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
ListIndexesIterable<Document> indexList = collection.listIndexes();
for(Document document : indexList) {
if("name_text".equals(document.get("name"))) {
return true;
}
}
return false;
}
});
if(hasIndex) {
System.out.println("name_text 已经存在,不再创建");
} else {
IndexDefinition indexDefinition = TextIndexDefinition.builder()
.named("name_text")
.onField("name")
.build();
String str = mongoTemplate.indexOps(Person.class).ensureIndex(indexDefinition);
System.out.println(str);
}
// 结果:
// name_text
}
}