简单双向@OneToOne存储null [英] Simple Bidirectional @OneToOne store null

查看:92
本文介绍了简单双向@OneToOne存储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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆