Simple Bidireccional @OneToOne store null
Intento seguir el ejemplo bidreccional @OneToOne de la documentación, pero siempre tengo una referencia nula en la columna PhoneDetails phone_id, y obtengo un teléfono con detalles nulos cuando obtengo.
Sigo la documentación que crea las clases Phone y PhoneDetails como se dice.
Pero debido a que la documentación no especifica cómo probar y necesito desarrollar una aplicación Spring Boot, creo una para probar y tal vez, en cualquier paso de esto, tenga el error.
Estos son mis pasos y el código que actualizo a github con la esperanza de que alguien pueda revisarlo
1 - Cree una aplicación Spring Boot en Eclipse con el conjunto de herramientas Spring con Java Versión 8
2 - Agregar dependencias MySqlDriver y Spring Web
3 - Agregue dependencia en el pom a spring-boot-starter-data-jpa
4 - Cree paquetes en el paquete principal (com.onetoone) para modelos, controladores y repositorio
5 - Cree en el paquete del modelo las clases Phone y PhoneDetails como se indica en el paquete de documentación com.onetoone.models;
@Entity(name = "Phone")
public class Phone {
@Id
@GeneratedValue
private Long id;
@Column(name = "`number`")
private String number;
@OneToOne(
mappedBy = "phone",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private PhoneDetails details;
//Getters and setters are omitted for brevity
public void addDetails(PhoneDetails details) {
details.setPhone( this );
this.details = details;
}
public void removeDetails() {
if ( details != null ) {
details.setPhone( null );
this.details = null;
}
}
}
@Entity(name = "PhoneDetails")
public class PhoneDetails {
@Id
@GeneratedValue
private Long id;
private String provider;
private String technology;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "phone_id")
private Phone phone;
//Getters and setters are omitted for brevity
}
En la documentación, crean estas clases como estáticas, pero tengo que eliminarlas porque Eclipse dice: "Modificador ilegal para la clase Teléfono; solo se permiten públicos, abstractos y finales". Importo todas las anotaciones (@Entity, @Id ...) de javax.persistence.
6 - Crear interfaz PhoneController en su paquete
package com.onetoone.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.onetoone.models.Phone;
public interface PhoneRepository extends JpaRepository<Phone, Long> {
}
7 - Crear PhoneController
package com.onetoone.controllers;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.onetoone.models.Phone;
import com.onetoone.repository.PhoneRepository;
@RestController
@RequestMapping("/phone")
public class PhoneController {
@Autowired
PhoneRepository phoneRepository;
@PostMapping("/save")
public ResponseEntity<Boolean> savePhone(@RequestBody Phone phone) {
phoneRepository.save(phone);
return ResponseEntity.ok(true);
}
@PostMapping("/get")
public ResponseEntity<Optional<Phone>> getPhone(@RequestBody int i) {
Long id = Long.valueOf(i);
Optional<Phone> phone = phoneRepository.findById(id);
return ResponseEntity.ok(phone);
}
}
8 - Establezca application.properties en su archivo en src / main / resources
spring.datasource.url= jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.username= root
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto= update
Tengo que agregar el? ServerTimezone = UTC a la URL de la base de datos para evitar un error.
9 - Crea un esquema en mi base de datos local llamado prueba
10 - Inicie la aplicación con Spring Boot Dashboard, y cree las tablas 'phone' y 'phone_details' (también otra llamada 'hibernate_sequence')
11- Uso cartero para enviar un descanso a esta url http: // localhost: 8080 / phone / save whit this body
{
"number": "123-456-7890",
"details": {
"provider": "T-Mobile",
"technology": "GSM"
}
}
12 - Y aquí está el problema. Crea una entrada en la tabla de teléfonos (id, número)
'1', '123-456-7890'
y otros en la tabla phone_details (id, proveedor, tecnología, phone_id)
'2', 'T-Mobile', 'GSM', NULL
13 - Por supuesto, si hago una publicación en la url http: // localhost: 8080 / phone / get con body 1 recibo
{
"id": 1,
"number": "123-456-7890",
"details": null
}
Espero que alguien pueda ayudarme porque trato de reducir el código al mínimo para seguir la documentación y aún tengo el problema :-(
La solución dada por @JavaMan es suficiente para el ejemplo, pero no para un objeto complejo. Espero que alguien más pueda ayudarme !!!
Respuestas
En su PhoneController, debe agregar la línea phone.getDetails (). SetPhone (phone); de lo contrario, el objeto de detalles no tendrá una referencia al teléfono.
Asi que asi
@PostMapping("/save")
public ResponseEntity<Boolean> savePhone(@RequestBody Phone phone) {
phone.getDetails().setPhone(phone);
phoneRepository.save(phone);
return ResponseEntity.ok(true);
}
Además, para que el código se ejecute, agregue la @JsonIgnoreanotación a su campo Teléfono en su clase PhoneDetails.