【问题标题】:Three entities mapping is not working properly because of lazy/eager loading in JPA由于 JPA 中的延迟/急切加载,三个实体映射无法正常工作
【发布时间】:2018-11-27 13:12:48
【问题描述】:

我正在映射三个实体。医生、客户(延伸一个人)和医疗咨询。 请参阅我上面的代码。考虑所有具有默认构造函数的模型类、具有所有字段的构造函数以及 getter 和 setter:

@Entity
@Table (name= "person")

public abstract class Person {

@Id @GeneratedValue
protected Long id;
protected String name;
protected String email;
protected String password;

@OneToOne
protected Address address;

现在是医生类。

@Entity(name = "doctor")
public class Doctor extends Person{
@OneToMany(mappedBy="doctor" , fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JsonManagedReference(value = "job-historical")
private List<MedicalConsultation> medicalConsultations;

@Enumerated
private Type type;

@ElementCollection
private List<String> specialties;
public Doctor() {
        super();
    }

public Doctor(String name, String email, String password, Address address, 
        List<String> specialties, Type type, 
        List<MedicalConsultation> medicalConsultations) {

    super(name,email,password,address);
    this.setMedicalConsultations(medicalConsultations);
    this.setSpecialties(specialties);
    this.setType(type);
}

我的构造函数调用super() 并根据超类及其自身属性设置它们的值。 Client 类也是如此。

@Entity(name = "client")
public class Client extends Person{

    @JsonManagedReference(value = "client-consultations-historical")
    @OneToMany(mappedBy="doctor" , fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<MedicalConsultation> medicalConsultations;

这里是医疗咨询模型,其中包含其他两个模型

@Entity
@Table(name = "medical_consultation")
public class MedicalConsultation {

    @Id
    @GeneratedValue
    private Long id;

    @JsonBackReference(value = "job-historical")
    @ManyToOne
    @JoinColumn(name="doctor_fk")
    private Doctor doctor;

    @ManyToOne
    @JoinColumn(name="client_fk")
    @JsonBackReference( value = "client-consultations-historical")
    private Client client;

    @JsonFormat(pattern = "dd/MM/yyyy hh:mm")
    private Date date;

    private BigDecimal price;

最后,我们遇到了问题: 在我的控制器类上,我无法获得医疗咨询的完整数据。也就是说,我得到了数据、ID 和价格,但由于某种原因我没有得到 Client 和 Doctor。 但是,如果我调用方法 getDoctor()getClient 并返回其中之一,我确实会看到所有信息。

查看 RestControl 类的方法:

@RestController
public class Control {

@Autowired
private PersonRepository personRepo;
@Autowired
private ClientRepository clientRepo;
@Autowired
private AddressRepository addressRepo;
@Autowired
private DoctorRepository doctorRepo;
@Autowired
private MedicalConsultationRepository consultationRepo;
@GetMapping("consultations")
    public List<MedicalConsultation> getConsultations() {
        List<MedicalConsultation> consultations = this.consultationRepo.findAll();
        return consultations;
    }

也许映射有问题。但是我将休眠设置为显示 sql,它显然使所有查询都得到了我想要的一切。见:

Hibernate: 
    select
        medicalcon0_.id as id1_2_,
        medicalcon0_.client_fk as client_f4_2_,
        medicalcon0_.date as date2_2_,
        medicalcon0_.doctor_fk as doctor_f5_2_,
        medicalcon0_.price as price3_2_ 
    from
        medical_consultation medicalcon0_
Hibernate: 
    select
        client0_.id as id2_3_0_,
        client0_.address_id as address_7_3_0_,
        client0_.email as email3_3_0_,
        client0_.name as name4_3_0_,
        client0_.password as password5_3_0_,
        address1_.id as id1_0_1_,
        address1_.city as city2_0_1_,
        address1_.number as number3_0_1_,
        address1_.phone as phone4_0_1_,
        address1_.street as street5_0_1_,
        medicalcon2_.doctor_fk as doctor_f5_2_2_,
        medicalcon2_.id as id1_2_2_,
        medicalcon2_.id as id1_2_3_,
        medicalcon2_.client_fk as client_f4_2_3_,
        medicalcon2_.date as date2_2_3_,
        medicalcon2_.doctor_fk as doctor_f5_2_3_,
        medicalcon2_.price as price3_2_3_,
        client3_.id as id2_3_4_,
        client3_.address_id as address_7_3_4_,
        client3_.email as email3_3_4_,
        client3_.name as name4_3_4_,
        client3_.password as password5_3_4_ 
    from
        person client0_ 
    left outer join
        address address1_ 
            on client0_.address_id=address1_.id 
    left outer join
        medical_consultation medicalcon2_ 
            on client0_.id=medicalcon2_.doctor_fk 
    left outer join
        person client3_ 
            on medicalcon2_.client_fk=client3_.id 
    where
        client0_.id=? 
        and client0_.dtype='client'
Hibernate: 
    select
        doctor0_.id as id2_3_0_,
        doctor0_.address_id as address_7_3_0_,
        doctor0_.email as email3_3_0_,
        doctor0_.name as name4_3_0_,
        doctor0_.password as password5_3_0_,
        doctor0_.type as type6_3_0_,
        address1_.id as id1_0_1_,
        address1_.city as city2_0_1_,
        address1_.number as number3_0_1_,
        address1_.phone as phone4_0_1_,
        address1_.street as street5_0_1_,
        medicalcon2_.doctor_fk as doctor_f5_2_2_,
        medicalcon2_.id as id1_2_2_,
        medicalcon2_.id as id1_2_3_,
        medicalcon2_.client_fk as client_f4_2_3_,
        medicalcon2_.date as date2_2_3_,
        medicalcon2_.doctor_fk as doctor_f5_2_3_,
        medicalcon2_.price as price3_2_3_,
        client3_.id as id2_3_4_,
        client3_.address_id as address_7_3_4_,
        client3_.email as email3_3_4_,
        client3_.name as name4_3_4_,
        client3_.password as password5_3_4_ 
    from
        person doctor0_ 
    left outer join
        address address1_ 
            on doctor0_.address_id=address1_.id 
    left outer join
        medical_consultation medicalcon2_ 
            on doctor0_.id=medicalcon2_.doctor_fk 
    left outer join
        person client3_ 
            on medicalcon2_.client_fk=client3_.id 
    where
        doctor0_.id=? 
        and doctor0_.dtype='doctor'

谁能告诉我发生了什么?

【问题讨论】:

  • 您的 MedicalConsultation 实体在哪里?向我们展示 MedicalConsultation,以便我们了解您如何映射它们
  • 对不起。我忘记了。
  • MedicalConsultation 中对于ClientDoctor,将@ManyToOne 中的fetchtype 设置为eager 并查看是否有效。 (即@ManyToOne (fetch = FetchType.EAGER)
  • 我忘了告诉我我已经尝试过了。它没有奏效。
  • 您是否尝试删除@JsonBackReference(value = "job-historical")@JsonBackReference( value = "client-consultations-historical")?因此,它不会序列化 Client 或 Doctor。

标签: java spring-boot jpa


【解决方案1】:

尝试在 MedicalConsultation 上映射注释,如下所示。

@ManyToOne(fetch = FetchType.EAGER)
private Doctor doctor;

【讨论】:

  • 我忘了告诉我我已经尝试过了。它没有奏效。
  • 我尝试使用 typescript 使用它,但我收到一条错误消息,提示无法读取属性“person”。也许我在这里遇到了问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-14
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多