我正在使用 Spring Boot 和 Kotlin 构建 API。我正在尝试在 MongoDB 中按以下方式生成结构。
我了解到在 MongoDb 中不存在实体之间关系的概念,所以我将使用嵌入文档的策略。也就是说,在 Proyecto 中嵌入 Reunión,在 Reunión 中嵌入 Participante。
我有一个名为Proyecto
and的主类NewProyecto
,它包含一个类型为 reuniones 的列表作为属性NewReunion
。我使用两个不同的类来创建和返回数据。
项目.kt
@Document(collection = "proyectos")
@TypeAlias("proyecto")
data class Proyecto (
@Id
val id: String,
val nombre: String,
val area: String,
val fecha:String,
val reuniones: List<Reunion>?
){}
@Document(collection = "proyectos")
@TypeAlias("newproyecto")
data class NewProyecto (
@Id
val id: String?,//Es posiblemente nulo porqué se crea automáticamente
var nombre: String,
var area: String,
var fecha:String,
var reuniones: List<NewReunion>?
){}
现在,为了创建“团聚”,我有两个类,Reunion
和NewReunion
. 对应于创建 MongoDB 嵌入文档的类是NewReunion
.
新团圆.kt
@Document
data class Reunion(
val objetivo: String,
val fecha: String,
val participantes: List<Participante>?
) {}
@Document
data class NewReunion(
var id: String? = ObjectId().toHexString(),
var fecha: String,
var participantes: List<NewParticipante>?
) {}
这是我有问题的地方。我想为这个NewReunion
类生成一个 ObjectId ,以便嵌入其中的每个对象都有一个id
. 的问题是,ObjectId ().ToHexString()
不产生在该类型的对象中的任何时间值NewReunion
是建立,但是其他数据objetivo
,并fecha
填充有来自POST请求中的数据。
我如何发送信息。
我通过POST
. 此请求由名为的控制器处理ProyectoController.kt
项目控制器.kt
@PostMapping("/")
fun createProyecto(@RequestBody newProyecto: NewProyecto): NewProyecto = proyectoService.createProyecto(newProyecto)
项目库.kt
interface ProyectoRepository : MongoRepository<Proyecto, String> {
fun findById(id: ObjectId): Proyecto
override fun findAll(): List<Proyecto>
fun insert(proyecto: NewProyecto): NewProyecto
fun save(proyect: Proyecto): Proyecto
fun deleteById(id: ObjectId)
}
项目服务.kt
@Service("proyectoService")
class ProyectoServiceImpl : ProyectoService {
@Autowired
lateinit var proyectoRepository: ProyectoRepository
//Obtener un proyecto
override fun findById(id: ObjectId): Proyecto = proyectoRepository.findById(id)
//Obtener todos los proyectos
override fun findAll(): List<Proyecto> = proyectoRepository.findAll()
//Crear un proyecto
override fun createProyecto(newProyecto: NewProyecto): NewProyecto = proyectoRepository.insert(newProyecto)
//Actualizar un proyecto
override fun updateProyecto(proyecto: Proyecto):Proyecto = proyectoRepository.save(proyecto)
//Eliminar un proyecto
override fun deleteProyecto(id:ObjectId) = proyectoRepository.deleteById(id)
}
使用邮递员发布:
在创建 new 时Proyecto
,我返回它以查看返回结果的结果id=null
,但所有其他字段都分配了相应的值:
现在,我尝试初始化 NewReunion 类的所有构造函数参数以查看发生了什么。
data class NewReunion(
@Id
var id: String? = ObjectId().toHexString(),
var objetivo: String = "",
var fecha: String = ""
) {}
的值id
与其他值一起正确生成。正是这种行为,我不明白为什么我需要初始化NewReunion
类的构造函数参数。
带有初始化参数的 POST 结果。
构建.gradle
buildscript {
ext.kotlin_version = '1.2.71'
ext {
kotlinVersion = '1.2.71'
springBootVersion = '2.0.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'
group = 'com.gibranlara'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
repositories {
mavenCentral()
}
configurations {
providedRuntime
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // Required for Kotlin integration
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "org.springframework.boot:spring-boot-starter-data-mongodb"
compile 'org.springframework.boot:spring-boot-starter-web'
}
您使用的库可能不是用 Kotlin 编写的。
Kotlin 生成一个合成构造函数,在调用实际构造函数之前加载默认值,例如
// Java
public NewReunion(String var1, String var2, String var3, int var4, DefaultConstructorMarker var5) {
if ((var4 & 1) != 0) {
var1 = ObjectId().toHexString();
}
this(var1, var2, var3);
}
The library is likely doing one of the following:
NewReunion(@Nullable String id, @NotNull String objetivo, @NotNull String fecha)
with NewReunion(null, "objetivo", "fecha")
If you define your class as such:
data class NewReunion @JvmOverloads constructor(
var id: String? = "",
var objetivo: String,
var fecha: String
)
You will get additional constructors e.g.
// Java
public NewReunion(@NotNull String objetivo, @NotNull String fecha)
If your library is using the first option then you may need to lazy initialize the id
field in a getter (also convert data class to normal class).
Most of these kind of problems stem from devs using the same object model for communication and business logic. Whenever I see a nullable id
on an entity it like a clarion call that bugs are afoot.
你从外部来源获得的任何数据(即使它来自你控制的服务器)都应该被视为是你最邪恶的敌人把它放在那里,但许多开发人员只是吸收它并在它出现时使用它。
如果你没有类似的东西
val cleanData = validate(inputData)
在从输入层过渡到业务层之前,您正在为未来的尴尬做好准备。
输入层是:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句