admin管理员组文章数量:1291818
I am using Spring Boot with MongoDB and implementing a multi-tenant architecture where each tenant has a separate database. I set the database dynamically using a custom MongoDatabaseFactory.
Even though I have @Indexed annotations in my entity classes and spring.data.mongodb.auto-index-creation=true in application.properties, indexes are not being created automatically when a new tenant database is initialized.
Note: I have no problems with dynamically changing database, CRUD operations, everything works properly, only index creation does not work.
What I tried:
- Enabled debug logging → No logs showing index creation attempts.
- Checked MongoDB shell (db.getIndexes()) → Only the default _id index is there.
- Manually creating indexes works (db.collection.createIndex(...)).
My Question:
How can I make Spring Boot automatically create indexes for new tenant databases when they are first accessed?
My dynamic database changing codes:
class MultiTenantMongoDbFactory(
private val mongoClient: MongoClient
) : MongoDatabaseFactory {
private val exceptionTranslator = MongoExceptionTranslator()
override fun getSession(options: ClientSessionOptions): ClientSession {
return mongoClient.startSession(options)
}
override fun getMongoDatabase(): MongoDatabase {
val dbName = DatabaseContext.getDatabaseName()
println("Switching to database: $dbName")
return mongoClient.getDatabase(dbName)
}
override fun getMongoDatabase(dbName: String): MongoDatabase {
return mongoClient.getDatabase(dbName)
}
override fun getExceptionTranslator(): PersistenceExceptionTranslator {
return exceptionTranslator
}
override fun withSession(session: ClientSession): MongoDatabaseFactory {
return MultiTenantMongoDbFactory(mongoClient).apply {
session
}
}
}
@Configuration
class MongoConfiguration {
@Value("\${SPRING_DATA_MONGODB_URI}")
lateinit var mongoURI: String
@Bean
fun mongoClient(): MongoClient {
return MongoClients.create(mongoURI)
}
@Bean
@Primary
fun multiTenantMongoDatabaseFactory(mongoClient: MongoClient): MultiTenantMongoDbFactory {
return MultiTenantMongoDbFactory(mongoClient)
}
@Bean
fun mongoTemplate(multiTenantMongoDatabaseFactory: MultiTenantMongoDbFactory): MongoTemplate {
val mongoTemplate = MongoTemplate(multiTenantMongoDatabaseFactory)
mongoTemplate.setReadPreference(ReadPreference.secondaryPreferred())
return mongoTemplate
}
}
object DatabaseContext {
private val contextHolder = ThreadLocal<String>()
private const val DEFAULT_DATABASE = "mydb"
fun setDatabaseName(dbName: String) {
contextHolder.set(dbName)
}
fun getDefaultDatabaseName(): String {
return DEFAULT_DATABASE
}
fun getDatabaseName(): String {
return contextHolder.get() ?: DEFAULT_DATABASE
}
fun clear() = contextHolder.remove()
}
Example data class;
@Document(collection = "users")
data class User(
@Id
val userId: String? = null,
@Indexed(name = "user_uuid_1", unique = true)
@Field("user_uuid")
var userUuid: String
)
application.properties;
spring.data.mongodb.auto-index-creation=true
logging.level.springframework.data.mongodb=DEBUG
logging.level.springframework.data.mongodb.core.index=DEBUG
...
...
I am using Spring Boot with MongoDB and implementing a multi-tenant architecture where each tenant has a separate database. I set the database dynamically using a custom MongoDatabaseFactory.
Even though I have @Indexed annotations in my entity classes and spring.data.mongodb.auto-index-creation=true in application.properties, indexes are not being created automatically when a new tenant database is initialized.
Note: I have no problems with dynamically changing database, CRUD operations, everything works properly, only index creation does not work.
What I tried:
- Enabled debug logging → No logs showing index creation attempts.
- Checked MongoDB shell (db.getIndexes()) → Only the default _id index is there.
- Manually creating indexes works (db.collection.createIndex(...)).
My Question:
How can I make Spring Boot automatically create indexes for new tenant databases when they are first accessed?
My dynamic database changing codes:
class MultiTenantMongoDbFactory(
private val mongoClient: MongoClient
) : MongoDatabaseFactory {
private val exceptionTranslator = MongoExceptionTranslator()
override fun getSession(options: ClientSessionOptions): ClientSession {
return mongoClient.startSession(options)
}
override fun getMongoDatabase(): MongoDatabase {
val dbName = DatabaseContext.getDatabaseName()
println("Switching to database: $dbName")
return mongoClient.getDatabase(dbName)
}
override fun getMongoDatabase(dbName: String): MongoDatabase {
return mongoClient.getDatabase(dbName)
}
override fun getExceptionTranslator(): PersistenceExceptionTranslator {
return exceptionTranslator
}
override fun withSession(session: ClientSession): MongoDatabaseFactory {
return MultiTenantMongoDbFactory(mongoClient).apply {
session
}
}
}
@Configuration
class MongoConfiguration {
@Value("\${SPRING_DATA_MONGODB_URI}")
lateinit var mongoURI: String
@Bean
fun mongoClient(): MongoClient {
return MongoClients.create(mongoURI)
}
@Bean
@Primary
fun multiTenantMongoDatabaseFactory(mongoClient: MongoClient): MultiTenantMongoDbFactory {
return MultiTenantMongoDbFactory(mongoClient)
}
@Bean
fun mongoTemplate(multiTenantMongoDatabaseFactory: MultiTenantMongoDbFactory): MongoTemplate {
val mongoTemplate = MongoTemplate(multiTenantMongoDatabaseFactory)
mongoTemplate.setReadPreference(ReadPreference.secondaryPreferred())
return mongoTemplate
}
}
object DatabaseContext {
private val contextHolder = ThreadLocal<String>()
private const val DEFAULT_DATABASE = "mydb"
fun setDatabaseName(dbName: String) {
contextHolder.set(dbName)
}
fun getDefaultDatabaseName(): String {
return DEFAULT_DATABASE
}
fun getDatabaseName(): String {
return contextHolder.get() ?: DEFAULT_DATABASE
}
fun clear() = contextHolder.remove()
}
Example data class;
@Document(collection = "users")
data class User(
@Id
val userId: String? = null,
@Indexed(name = "user_uuid_1", unique = true)
@Field("user_uuid")
var userUuid: String
)
application.properties;
spring.data.mongodb.auto-index-creation=true
logging.level..springframework.data.mongodb=DEBUG
logging.level..springframework.data.mongodb.core.index=DEBUG
...
...
Share
Improve this question
asked Feb 13 at 13:06
Ozgur BaykalOzgur Baykal
4232 silver badges13 bronze badges
2
- It must be a lifecycle matter. I reckon your Spring Boot App starts up, connects to the "default" database then does its Index checking. Later you switch database, but now it is too late. So dig around to look for how/when the index creation process executes and work from there; perhaps you can re-invoke the index check/creation code. – AndrewL Commented Feb 17 at 23:10
- Yes you are right, when Spring Boot first starts, it connects to a default database and creates indexes only for that database. However, when I dynamically change the database, it cannot apply these indexes to other databases. And there is no solution. So I have to create indexes for each database manually from MongoDB Compass or shell. (Or as I do now, when a customer is created in CRM, I switch to the customer's database and create indexes manually with indexOps()). – Ozgur Baykal Commented Feb 21 at 12:27
1 Answer
Reset to default 1When Spring Boot first starts, it connects to a default database and creates indexes only for that database.
However, when I dynamically change the database, it cannot apply these indexes to other databases. And there is no solution for this.
So you have to manually create indexes for each database from MongoDB Compass or shell.
Or as I am doing now, when a customer is created in CRM, I switch to the customer's database and create indexes manually with indexOps().
You can solve the problem if you include this code it in a scenario where you create a new database.
DatabaseContext.setDatabaseName(request.dbName)
mongoTemplate.indexOps("devices").ensureIndex(
Index().on("device_uuid", Sort.Direction.ASC).unique()
)
mongoTemplate.indexOps("devices").ensureIndex(
Index().on("user_uuid", Sort.Direction.ASC)
)
mongoTemplate.indexOps("devices").ensureIndex(
Index().on("is_active", Sort.Direction.ASC)
)
mongoTemplate.indexOps("users").ensureIndex(
Index().on("user_uuid", Sort.Direction.ASC).unique()
)
本文标签: MongoDB Indexes Not Created Automatically in Spring Boot with MultiTenant DatabaseStack Overflow
版权声明:本文标题:MongoDB Indexes Not Created Automatically in Spring Boot with Multi-Tenant Database - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741539310a2384226.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论