问题
I try to follow the @OneToOne bidrectional example from documetation but I always have a null reference in the PhoneDetails phone_id colum, and obtein a Phone with null details when do a get.
I follow the documentation creating Phone and PhoneDetails Classes as is say.
But because the documentation don't specify how to test and I need to develop an Spring Boot app, I create one to test and maybe, in any step of this I have the error.
Here are my steps, and the code I update to github hoping someone can review it
1 - Create a Spring Boot App in Eclipse with Spring tool suite with Java Version 8
2 - Add dependencies MySqlDriver and Spring Web
3 - Add dependency in the pom to spring-boot-starter-data-jpa
4 - Create packages under the main package (com.onetoone) for models, controllers and repository
5 - Create in the model package the classes Phone y PhoneDetails as say in documentation package 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
}
In documentation they create this classes as static, but I have to remove it because Eclipse says: "Illegal modifier for the class Phone; only public, abstract & final are permitted". I import all the anotations (@Entity, @Id...) from javax.persistence.
6 - Create interface PhoneController in his package
package com.onetoone.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.onetoone.models.Phone;
public interface PhoneRepository extends JpaRepository<Phone, Long> {
}
7 - Create 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 - Set the application.properties in his file under 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
I have to add the ?serverTimezone=UTC to the database url to avoid an error.
9 - Create an schema in my local database called test
10 - Start the app with Spring Boot Dashboard, and it create the tables 'phone' and 'phone_details' (also another one called 'hibernate_sequence')
11- I use postman to send a rest to this url http://localhost:8080/phone/save whit this body
{
"number": "123-456-7890",
"details": {
"provider": "T-Mobile",
"technology": "GSM"
}
}
12 - And here is the problem. It create an entry in the phone table (id, number)
'1', '123-456-7890'
and other in the phone_details table (id, provider, technology, phone_id)
'2', 'T-Mobile', 'GSM', NULL
13 - Of course, if I do a post to url http://localhost:8080/phone/get with body 1 I recibe
{
"id": 1,
"number": "123-456-7890",
"details": null
}
I hope anybody can help me because I try to reduce the code to the minimun to follow the documentation and still I have the issue :-(
The solution gives by @JavaMan is enought for the example, but not for a complex object. I hope someoneelse can help me!!!
回答1:
In your PhoneController, you have to add the line phone.getDetails().setPhone(phone); otherwise the details object will not have a reference to the phone.
So like this
@PostMapping("/save")
public ResponseEntity<Boolean> savePhone(@RequestBody Phone phone) {
phone.getDetails().setPhone(phone);
phoneRepository.save(phone);
return ResponseEntity.ok(true);
}
Also, to get the code running add the @JsonIgnore
annotation to your Phone field in your PhoneDetails class.
来源:https://stackoverflow.com/questions/64733460/simple-bidirectional-onetoone-store-null