Creé una entidad (modelo o clase de datos) en un proyecto Spring-Boot (Kotlin) que contiene un campo con el tipo Arraylist, pero cuando envío una matriz de datos en formato JSON desde Postman, la matriz se almacena en la base de datos durante mucho tiempo. cadena aleatoria.
Cuando trato de recuperar los datos de la base de datos, obtengo la matriz real, perfectamente formateada.
Mi pregunta es ¿por qué se almacena una ArrayList en una base de datos H2 como esta?
Evaluación.kt
@Entity data class Evaluation ( @Id val id : String, val timeStamp : Long, val symptoms : ArrayList<String>, val travelHistory : Boolean, val contactWithCovidPatient : Boolean, val evaluatedBy : String, var evaluationPercentage : String? = null, @ManyToOne var user: User? = null )EvaluationController.kt
@RestController class EvaluationController (val evaluationService: IEvaluationService) { @PostMapping("evaluate/{userId}") fun evaluateUser(@PathVariable userId : String, @RequestBody evaluation: Evaluation) : ResponseEntity<Evaluation> = ResponseEntity.ok().body(evaluationService.addEvaluation(evaluation, userId)) }Cuerpo de solicitud JSON
{ "id":"e_01", "timeStamp":"123456789", "pinCode":"123457", "travelHistory":true, "contactWithCovidPatient":true, "evaluatedBy":"u_01", "symptoms": ["Fever","Cough"] }JSON de respuesta
{ "id": "e_01", "timeStamp": 123456789, "symptoms": [ "Fever", "Cough" ], "travelHistory": true, "contactWithCovidPatient": true, "evaluatedBy": "u_01", "evaluationPercentage": "95", "user": { "id": "u_01", "name": "abc01", "phoneNumber": "9876543210", "pinCode": "123457", "covidResult": "Positive" } }Tabla de base de datos H2
Esta es una cadena hexadecimal que representa el objeto ArrayList serializado. Consulte Objetos serializables para obtener detalles sobre la serialización de objetos en Java.
Ejecutar el siguiente código produce el mismo resultado:
List<String> symptoms = new ArrayList<>(Arrays.asList("Fever", "Cough")); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(symptoms); byte[] serializedObject = byteArrayOutputStream.toByteArray(); String hex = Hex.encodeHexString(serializedObject); // Apache Commons Codec System.out.println(hex); aced0005737200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a657870000000027704000000027400054665766572740005436f75676878La cadena sin procesar que se ve en la base de datos es un objeto serializado.
Una forma de implementar esto es unir primero su cadena ArrayList en una cadena delimitada, pero recomiendo encarecidamente no hacerlo. En general, es una mala práctica colocar una lista en un solo campo de una tabla. Lo que debería estar haciendo es crear una tabla separada para Síntomas con una relación de uno a muchos con Evaluación.
Debe tener en cuenta la desnormalización al diseñar sus objetos cuando usa JPA. En tu caso, plantéate las siguientes cuestiones:
Si alguna vez se encuentra en una situación en la que intenta agregar una colección de algo en un campo de base de datos, el 99,9999% de las veces lo está haciendo mal. Los síntomas deben ser una entidad propia, y usted tiene una relación de uno a muchos o de muchos a muchos entre la evaluación y el síntoma, según lo que necesite.
Editar :
Para aclarar aún más mi respuesta, al diseñar clases de objetos, piense si un campo es un objeto de valor o una entidad. Un objeto de valor es algo que no se puede desglosar más y se puede representar mediante una primitiva, como Fecha, Cadena, Int, etc. Algunos ejemplos podrían ser un ID de objeto, un nombre, un número de teléfono, etc.
Una entidad es un objeto que se puede expandir aún más, como el objeto Evaluaciones que creó. Dentro de Evaluaciones, tiene una lista de Síntomas y está tratando los Síntomas como un objeto de valor. Sin embargo, ¿es un objeto de valor? Inmediatamente puedo pensar en algunos campos adicionales que podría poner en un objeto Síntoma, y al desnormalizar los síntomas de la forma en que lo hizo, también está ingresando toneladas de datos duplicados en la base de datos.
Un objeto de evaluación que contenga ["Fiebre", "Tos"] en su implementación se ingresará en la base de datos como un campo. Pero otro objeto de evaluación que contiene los mismos síntomas se ingresará en la base de datos para esa evaluación porque no tiene una dependencia de clave externa o una tabla separada que represente los síntomas. Además de no poder consultar síntomas en relación con evaluaciones, o no poder consultar síntomas por sí solos.