spring-data-jpa Sping Boot REST API中的一对多关系

w9apscun  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(170)

我使用 Boot 创建了一个RESTAPI。在这个API中,我在check-inGuests之间建立了一个一对多的关系。我创建了一个用于签入的控制器,并使用springJPA的保存函数。save方法同时更新了check-inguests表,但对于guests表,未添加***guest表***中的签入外键,而是显示为空。请帮助我。我需要同时创建guest和签入。

签入模型

@Data
@Entity
public class Checkin {

    @Id
    private Long id;

    private Integer no_of_guests;

    @OneToMany(mappedBy = "checkin", cascade = CascadeType.ALL)
    private List<Guest> guests;
}

访客模型

@Data
@Entity
public class Guest {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long guest_id;

    private String name;

    private String mobile_no;

    private String address;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "guest_checkin_id", nullable = false )
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private Checkin checkin;

}

值机员

@RestController
@RequestMapping("/checkin")
public class CheckinController {

    private final CheckinRepository checkinRepo;
    private final GuestRepository guestRepo;

    public CheckinController(CheckinRepository checkinRepo,GuestRepository guestRepo){
        this.checkinRepo = checkinRepo;
        this.guestRepo = guestRepo;
    }

    @PostMapping("/add")
    ResponseEntity<Object> roomCheckin(@RequestBody Checkin checkin){
         if(checkinRepo.save(checkin) != null){
            return ResponseEntity.accepted().body("Checkin Successfull");
        }
        return ResponseEntity.unprocessableEntity().body("Failed to Checkin");
    }
}
sy5wg1nm

sy5wg1nm1#

使用实体类作为视图模型类可能有点棘手,尤其是在CheckinGuest之间存在双向一对多关系的情况下。
让我们从验证实体类和仓库是否如所描述的那样工作开始。为了进行测试运行,我不得不为类Checkin中的id字段添加@GeneratedValue
其他变更:

为了验证代码,我在下面添加了一个测试类CheckinRepositoryTest
如前所述,使用实体类作为视图模型类可能比较棘手,因此下一步将引入两个新的视图模型类:CheckinVMGuestVM,以及一个新的服务类GuestService,该服务类负责保存CheckinGuest示例。代码如下所示。
请注意,我只添加了GuestService类的框架,我把它留给您来实现。CheckinRepositoryTest中的代码指示了如何实现它。
有了视图模型类,就应该删除@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
当所有部分都启动并运行后,您应该向新的视图模型类添加验证,以及一些验证行为的集成测试。
您还应该查看一下控制器方法,并在成功和失败情况下使用适当的状态代码。
访客级别

package no.mycompany.myapp.misc;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;

@Getter
@Setter
@Entity
public class Guest {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long guest_id;

    private String name;

    private String mobile_no;

    private String address;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "guest_checkin_id", nullable = false)
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private Checkin checkin;
}

GuestVM类

package no.mycompany.myapp.misc;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class GuestVM {

    private long id;
    private String name;
    private String mobile_no;
    private String address;

    public GuestVM(Guest guest) {
        this.id = guest.getGuest_id();
        this.name = guest.getName();
        this.mobile_no = guest.getMobile_no();
        this.address = guest.getAddress();
    }
}

签入类

package no.mycompany.myapp.misc;

import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
@Entity
public class Checkin {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Integer no_of_guests;

    @OneToMany(mappedBy = "checkin", cascade = CascadeType.ALL)
    private Set<Guest> guests = new HashSet<>();
}

签入VM类

package no.mycompany.myapp.misc;

import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.stream.Collectors;

@Getter
@Setter
@NoArgsConstructor
public class CheckinVM {

    private long id;
    private List<GuestVM> guests;

    public CheckinVM(Checkin checkin) {
        this.id = checkin.getId();
        this.guests = checkin.getGuests().stream().map(GuestVM::new).collect(Collectors.toList());
    }
}

签入存储库

package no.mycompany.myapp.misc;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CheckinRepository extends JpaRepository<Checkin, Long> { }

签入存储库测试

package no.mycompany.myapp.misc;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@DataJpaTest
public class CheckinRepositoryTest {

    @Autowired
    TestEntityManager testEntityManager;

    @Autowired
    CheckinRepository checkinRepository;

    @Test
    public void test() {

        // create instances
        var checkinInDb = new Checkin();
        var guestInDb = new Guest();

        // add relations
        guestInDb.setCheckin(checkinInDb);
        checkinInDb.getGuests().add(guestInDb);

        // save check-in
        checkinRepository.save(checkinInDb);

        // verify that check-in has one guest
        var checkin = testEntityManager.find(Checkin.class, checkinInDb.getId());
        assertThat(checkin.getGuests().size()).isEqualTo(1);

        // verify that guest is connected to a check-in
        var guest = testEntityManager.find(Guest.class, guestInDb.getGuest_id());
        assertThat(guest.getCheckin()).isNotNull();
    }
}

签入服务类:我把这个留给你去实现

package no.mycompany.myapp.misc;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class CheckinService {

    private final CheckinRepository checkinRepository;

    public CheckinVM saveCheckin(CheckinVM checkin) {
        return null; // TODO: implement this
    }
}

控制器类别

package no.mycompany.myapp.misc;

import lombok.RequiredArgsConstructor;
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;

@RestController
@RequestMapping("/checkin")
@RequiredArgsConstructor
public class CheckinController {

    private final CheckinService checkinService;

    @PostMapping("/add")
    ResponseEntity<Object> roomCheckin(@RequestBody CheckinVM checkin) {
        if (checkinService.saveCheckin(checkin) != null) {
            return ResponseEntity.accepted().body("Checkin Successful");
        }
        return ResponseEntity.unprocessableEntity().body("Failed to Checkin");
    }
}

相关问题