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 } }