Simple Bidirectional @OneToOne store null
Provo a seguire l' esempio bidirezionale @OneToOne da documetation ma ho sempre un riferimento nullo nella colonna PhoneDetails phone_id e ottengo un telefono con dettagli nulli quando eseguo un get.
Seguo la documentazione creando le classi Phone e PhoneDetails come si dice.
Ma poiché la documentazione non specifica come testare e ho bisogno di sviluppare un'app Spring Boot, ne creo una per testare e forse, in qualsiasi passaggio di questo, ho l'errore.
Ecco i miei passaggi e il codice che aggiorno a GitHub sperando che qualcuno possa esaminarlo
1 - Crea un'app Spring Boot in Eclipse con la suite di strumenti Spring con Java versione 8
2 - Aggiungi le dipendenze MySqlDriver e Spring Web
3 - Aggiungi la dipendenza nel pom a spring-boot-starter-data-jpa
4 - Creare pacchetti nel pacchetto principale (com.onetoone) per modelli, controller e repository
5 - Creare nel pacchetto modello le classi Phone y PhoneDetails come si dice nel pacchetto di documentazione 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
}
Nella documentazione creano queste classi come statiche, ma devo rimuoverle perché Eclipse dice: "Modificatore illegale per la classe Phone; sono consentiti solo public, abstract e final". Importo tutte le annotazioni (@Entity, @Id ...) da javax.persistence.
6 - Crea l'interfaccia PhoneController nel suo pacchetto
package com.onetoone.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.onetoone.models.Phone;
public interface PhoneRepository extends JpaRepository<Phone, Long> {
}
7 - Crea 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 - Imposta application.properties nel suo file sotto 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
Devo aggiungere? ServerTimezone = UTC all'URL del database per evitare un errore.
9 - Crea uno schema nel mio database locale chiamato test
10 - Avvia l'app con Spring Boot Dashboard e crea le tabelle 'phone' e 'phone_details' (anche un'altra chiamata 'hibernate_sequence')
11- Uso il postino per inviare una pausa a questo URL http: // localhost: 8080 / phone / save whit this body
{
"number": "123-456-7890",
"details": {
"provider": "T-Mobile",
"technology": "GSM"
}
}
12 - Ed ecco il problema. Crea una voce nella tabella del telefono (id, numero)
'1', '123-456-7890'
e altro nella tabella phone_details (id, provider, tecnologia, phone_id)
'2', 'T-Mobile', 'GSM', NULL
13 - Ovviamente, se faccio un post all'URL http: // localhost: 8080 / phone / get with body 1 lo ricevo
{
"id": 1,
"number": "123-456-7890",
"details": null
}
Spero che qualcuno possa aiutarmi perché cerco di ridurre il codice al minimo per seguire la documentazione e ancora ho il problema :-(
La soluzione fornita da @JavaMan è sufficiente per l'esempio, ma non per un oggetto complesso. Spero che qualcun altro possa aiutarmi !!!
Risposte
Nel tuo PhoneController, devi aggiungere la linea phone.getDetails (). SetPhone (phone); altrimenti l'oggetto dettagli non avrà un riferimento al telefono.
Quindi così
@PostMapping("/save")
public ResponseEntity<Boolean> savePhone(@RequestBody Phone phone) {
phone.getDetails().setPhone(phone);
phoneRepository.save(phone);
return ResponseEntity.ok(true);
}
Inoltre, per eseguire il codice, aggiungi l' @JsonIgnoreannotazione al campo Telefono nella classe PhoneDetails.