Spring Boot - 数据库操作之MongoDB
Spring Data提供了对MongDB的支持,在SpringBoot项目中集成MongoDB非常便捷。
1.快速集成
添加依赖
compile('org.springframework.boot:spring-boot-starter-data-mongodb:2.1.0.RELEASE')
application.properties或application.yml中配置mongodb相关项
spring:
data:
mongodb:
uri: mongodb://name:pass@localhost:27017/test
如果要连接MongoDB副本集,那么连接配置如下,replcaSet参数指定了副本集名称。
spring:
data:
mongodb:
uri: mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/test?replcaSet=xxx&slaveOk=true&readPreference=primary
使用MongoTemplate操作MongoDB
@RunWith(SpringRunner::class)
@SpringBootTest
class ApplicationTests {
@Autowired
private lateinit var mongoTemplate: MongoTemplate
@Test
fun test() {
mongoTemplate.insert(User(name = "jack", age = 16))
mongoTemplate.find(Query(),User::class.java).forEach { println(it.toString()) }
mongoTemplate.findAllAndRemove(Query(Criteria.where("name").`is`("jack")),User::class.java)
mongoTemplate.save(User(name = "tom", age = 17))
mongoTemplate.updateMulti(Query(Criteria.where("name").`is`("tom")), Update().set("age",18),User::class.java)
}
}
@Document(collection = "user")
data class User(
@Id
var id: String? = null,
@Field(value = "name")
var name: String? = null,
@Field(value = "age")
var age: Int? = null
)
上面的代码使用kotlin在Spring Boot中使用junit测试了MongoTemplate提供的部分函数,MongoTemplate支持的操作非常多,从函数名上看,与MongoDB原生的命令基本接近,这里不做过多展示了,实际应用中根据需要选择。
另外,除了使用MongoTemplate
操作MongoDB数据库,还可以使用MongoRepository
快速地实现CURD操作(这点类似JPA)。
例如使用MongDB实现小文件存储:
File.kt
@Document
data class File(
@Id
var id: String? = null,
var name: String? = null,
var contentType: String? = null,
var size: Long? = null,
var uploadDate: Date? = null,
var md5: String? = null,
var path: String? = null,
var content: Binary? = null
) {
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other == null || this::class.java != other::class.java) {
return false
}
val file: File = other as File
return Objects.equals(size, file.size)
&& Objects.equals(name, file.name)
&& Objects.equals(contentType, file.contentType)
&& Objects.equals(uploadDate, file.uploadDate)
&& Objects.equals(md5, file.md5)
&& Objects.equals(id, file.id)
}
override fun hashCode(): Int {
return Objects.hash(name, contentType, size, uploadDate, md5, id)
}
}
FileRepository.kt
@Repository
interface FileRepository: MongoRepository<File,String>
2.事务支持
MongoDB更新到4.0以后已经支持ACID及多文档事务。
当我们迫不及待地在Spring Boot项目中尝试这一特性的时候,发现仅仅使用@Transactional
注解是不能自动开启事务的。因为Spring Data MongoDB模块在默认情况下并没有注册PlatformTransactionManager
,这是为了防止在使用非4.0版本的MongoDB或者项目中已经使用了其它事务管理器的情况下的异常情况,所以需要手动配置事务管理器。
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.MongoDbFactory
import org.springframework.data.mongodb.MongoTransactionManager
@Configuration
class MongoConfig {
@Bean
fun transactionManager(dbFactory: MongoDbFactory): MongoTransactionManager {
return MongoTransactionManager(dbFactory)
}
}
需要说明的是,MongoTransactionManager事务管理器在Spring Data MongoDB 2.1版本后才能支持,详细信息见Spring Data MongoDB参考文档
有一些操作在MongoDB的事务中是不支持的,如几乎所有元命令、创建集合、创建索引、首次使用集合时隐时创建集合。
另外,千万不要在JUnit中测试验证MongoDB的事务回滚,因为@Rollback
默认为true强制回滚,这样就不知道是因为Junit回滚还是因为事务出现异常回滚,如果设为false又会使得MongoDB事务不会回滚......
参考
Hands on MongoDB 4.0 transactions with Spring Data
https://stackoverflow.com/questions/51977150/spring-data-mongodb-transactional-failure