简单双向@OneToOne存储null [英] Simple Bidirectional @OneToOne store null
问题描述
我尝试遵循我更新到github的代码希望有人可以对其进行审查>
1-使用带有Java版本8的Spring工具套件在Eclipse中创建Spring Boot应用程序
2-添加依赖MySqlDriver和Spring Web
3-将pom中的依赖项添加到spring-boot-starter-data-jpa
4-在主包(com.onetoone)下为模型,控制器和存储库创建包
5-在模型包中创建类Phone y PhoneDetails,如文档中所述 包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
}
在文档中,他们将这些类创建为静态类,但是我必须将其删除,因为Eclipse表示:"Phone类的非法修饰符;仅公开,抽象和最终许可". 我从javax.persistence导入了所有注释(@ Entity,@ Id ...).
6-在其程序包中创建接口PhoneController
package com.onetoone.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.onetoone.models.Phone;
public interface PhoneRepository extends JpaRepository<Phone, Long> {
}
7-创建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-在文件src/main/resources下设置application.properties
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
我必须将?serverTimezone = UTC添加到数据库URL中,以免发生错误.
9-在我的本地数据库中创建一个名为test的模式
10-使用Spring Boot Dashboard启动应用程序,并创建表"phone"和"phone_details"(另一个称为"hibernate_sequence"的表)
11-我使用邮递员将剩下的内容发送到该网址http://localhost:8080/phone/保存该主体
{
"number": "123-456-7890",
"details": {
"provider": "T-Mobile",
"technology": "GSM"
}
}
12-这是问题所在.它会在电话表中创建一个条目(ID,号码)
'1', '123-456-7890'
和phone_details表中的其他内容(id,提供商,技术,phone_id)
'2', 'T-Mobile', 'GSM', NULL
13-当然,如果我在网址1:http://localhost:8080/phone/get上贴上主体1,我会收信
{
"id": 1,
"number": "123-456-7890",
"details": null
}
我希望任何人都可以帮助我,因为我尝试将代码减少到遵循文档的最低要求,但仍然存在问题:-(
@JavaMan提供的解决方案足以满足示例要求,但不适用于复杂对象.我希望有人能帮助我!
在PhoneController中,您必须添加以下行 phone.getDetails().setPhone(phone);否则,Details对象将没有对电话的引用.
像这样
@PostMapping("/save")
public ResponseEntity<Boolean> savePhone(@RequestBody Phone phone) {
phone.getDetails().setPhone(phone);
phoneRepository.save(phone);
return ResponseEntity.ok(true);
}
此外,要使代码运行,请在PhoneDetails类的Phone字段中添加@JsonIgnore
批注.
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!!!
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.
这篇关于简单双向@OneToOne存储null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!