#spring #mongodb #spring-boot
#spring #mongodb #spring-boot
Вопрос:
Я работаю над новым проектом с использованием Spring и MongoDB. Я новичок в обоих из них, так что потерпите, я не смог найти окончательного ответа на этот вопрос.
Я использую spring-boot-starter-data-rest
и имею такой репозиторий:
@RepositoryRestResource(collectionResourceRel = "widget", path = "widget")
interface WidgetRepository : MongoRepository<Widget, ObjectId> {
fun findByType(@Param("type") type: String): List<Widget>
}
Для такого объекта, как этот:
data class Widget @JsonCreator constructor(@JsonProperty val type: String) {
@Id
lateinit var id: ObjectId
}
Это автоматически дает вам CRUD API с использованием идентификатора документа Mongo:
GET /widget/{mongo doc id}
GET /widget/search/findByType?type=
POST /widget
PUT /widget
PATCH /widget
Но я не хочу использовать идентификатор документа Mongo. Я хочу ввести дополнительный идентификатор и использовать его везде в API. Это связано с тем, что «виджеты» — это элементы в физическом мире, которые имеют штрих-код, и мы не хотим печатать идентификатор документа Mongo в штрих-коде.
Очевидно, что мы можем реализовать это с помощью инструментов Spring REST API, например
@GetMapping("/widget/{barcode}/")
fun getByBarcode(@PathVariable barcode: String): Widget {
return widgetRepository.findByBarcode(barcode)
}
и т. Д. Но есть ли какой-нибудь умный способ @RepositoryRestResource
создать для нас свой automagic API с пользовательским идентификатором? Может быть, путем реализации CrudRepository<Widget, Barcode>
таким образом, что мы должны обернуть MongoRepository<Widget, ObjectId>
? Я недостаточно знаком с тем, как Spring работает под капотом, чтобы знать, возможно ли что-то подобное.
Заранее спасибо
Комментарии:
1. Если ваш штрих-код является уникальным значением для каждого документа, то вместо ObjectId вы можете использовать Barcode в качестве _id . Значение _id документа может иметь любой тип BSON (кроме массива).
Ответ №1:
Я думаю, вы ищете EntityLookup
:
SPI для настройки того, какое свойство объекта используется в качестве уникального идентификатора и как экземпляр объекта просматривается из серверной части.
Во-первых — извините, если я допустил какую-либо ошибку, я не использую для программирования в Kotlin — вам необходимо включить barcode
свойство в свой объект:
data class Widget @JsonCreator constructor(@JsonProperty val type: String, @JsonProperty val barcode: String) {
@Id
lateinit var id: ObjectId
}
Затем измените свой репозиторий и определите новый метод, который предоставит Widget
данный его штрих-код:
@RepositoryRestResource(collectionResourceRel = "widget", path = "widget")
interface WidgetRepository : MongoRepository<Widget, ObjectId> {
fun findByBarcode(@Param("barcode") barcode: String): Optional<Widget>
fun findByType(@Param("type") type: String): List<Widget>
}
Наконец, настройте RestRepositoryConfigurer
и зарегистрируйте EntityLookup
EntityLookupRegistrar
:
@Component
class RestRepositoryConfigurator : RepositoryRestConfigurer {
override fun configureRepositoryRestConfiguration(config: RepositoryRestConfiguration) {
config.withEntityLookup()
.forRepository(WidgetRepository::class.java)
.withIdMapping(Widget::barcode)
.withLookup(WidgetRepository::findByBarcode)
}
}
Пожалуйста, ознакомьтесь с разделом 15.1
документации Spring Data Rest, если вам нужна дополнительная информация.
Комментарии:
1. @michiakig У вас была возможность протестировать предложенное решение?
2. привет, спасибо за вашу помощь, это работает. нам пришлось изменить
data class Widget
наopen class Widget
, поскольку была ошибка оWidget::barcode
том, что он является окончательным (классы kotlin являются окончательными по умолчанию)3. Добро пожаловать @michiakig. Я рад узнать, что ответ был полезным. И, пожалуйста, извините за ошибку в классе Kotlin, как я уже говорил, я понимаю код, когда вижу его, но я не использую для программирования в Kotlin
4. да, нет проблем, я включил эту деталь только для будущих читателей 🙂 еще раз спасибо