Spring Boot REST Api 中的一对多关系

2023-12-10

我正在使用 Spring Boot 创建 REST API。在此 API 中,我之间有一对多关系check-in and Guests。我创建了一个用于签入的控制器并使用 spring JPA 的保存功能。 保存方法正在更新两者checkin and 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");
    }
}

使用实体类作为视图模型类可能有点棘手,特别是在这种情况下,当实体类之间存在双向一对多关系时Checkin and Guest.

让我们首先验证实体类和存储库是否按所示工作。为了进行测试运行,我必须添加@GeneratedValue对于类中的 id 字段Checkin.

其他变化:

  • Use Set代替List. See https://stackoverflow.com/a/6563037/14072498
  • Use @Getter and @Setter代替@Data对于实体类 关系

我添加了一个测试类CheckinRepositoryTest下面为了验证代码。


如前所述,使用实体类作为视图模型类可能很棘手,因此下一步将引入两个新的视图模型类:CheckinVM and GuestVM,以及一个新的服务等级GuestService这将负责保存Checkin with Guest实例。代码如下所示。

请注意,我只添加了骨架GuestService班级,我把它留给你来实现。里面的代码CheckinRepositoryTest表明如何实现它。

有了视图模型类,@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)应该被删除。


所有部分都启动并运行后,您应该向新视图模型类添加验证,以及一些验证行为的集成测试。如果您遵循 TDD,您将按自己的方式添加测试。

您还应该查看您的控制器方法,并针对成功和失败情况使用适当的状态代码。


嘉宾班

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();
    }
}

CheckinService 类:我把这个留给你来实现

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");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot REST Api 中的一对多关系 的相关文章

随机推荐

  • tsconfig.json 中的 target 是做什么用的?

    什么是target in tsconfig json表示 compilerOptions sourceMap true target es5 module commonjs jsx react moduleResolution classi
  • Google 应用程序脚本中的 Adword 脚本

    我无法在 Google App 脚本中找到 Adword API 支持 我可以从 adword 帐户编写 adword 脚本 但目前我正在处理多个帐户 几乎 25 个 我要做的就是进入个人帐户并在其中复制我的脚本帐户和adword脚本有一个
  • 在pykml中读取带有多个地标的kml文件

    In pykml 我可以使用以下代码读取文件中的第一个地标 with open filename as f pm parser parse f getroot Document Folder print got print pm Place
  • 使用 Storyboard 和 Xcode 4.5 的 UIPageViewController

    我想问一些关于 Xcode 4 5 的问题 我正在使用故事板创建应用程序 这个应用程序有UIPageViewController 但是如果我想定义标识符UIViewController在情节提要的 IB 中 已经没有地方了 你能告诉我 我可
  • 如何进行跨站ajax请求?

    浏览器不允许跨站点 AJAX 调用 这是安全限制 有什么可能的解决办法吗 EDIT 我只控制来电者网站 如果你控制双方 那么就有很多选择 例如JSONP or 修改标题远程网站的响应 很遗憾 JSONP 仅在远程网站支持时才有效 你can
  • Opencv:在盒子中找到盒子

    后勤 opencv 2 4 和 Python 2 7 The image I m working with 问题 我感兴趣的是隔离围绕 9 条垂直线和水平线形成盒子的轮廓 我只是不确定该怎么做 我看过各种教程 例如关于数独谜题的教程 这些教
  • 通过引用临时传递函数的生命周期[重复]

    这个问题在这里已经有答案了 我可以做这样的事情 const int i 5 并将临时的生命周期延长到i 但怎么样 const int fun const int i return i int main const int r fun 5 C
  • matplotlib - 更改图大小但保持字体大小不变

    我想显示几个不同大小的图形 确保打印图形时文本始终具有相同的大小 我怎样才能做到这一点 举个例子 假设我有两个数字 import matplotlib pylab as plt import matplotlib as mpl mpl rc
  • Angular 9 通用错误:组件“HeaderComponent”未解析:

    更新到 Angular 9 和 Universal 9 后 运行时出现错误npm run build ssr npm run serve ssr Error Component HeaderComponent is not resolved
  • 疯狂邮件方法不起作用?

    在配置菜单下的 spree 管理面板中 我配置了邮件 smtp 端口等 创建新邮件方法后 我按下测试邮件按钮 我收到以下警报消息 测试邮件发送成功 甚至终端窗口也显示电子邮件发送成功消息 但是邮件未送达相应地址 发送测试邮件后控制台日志 S
  • 将装置转换为 Rails 中的 Factory Girl

    我想将我的装置迁移到 Rails 中的 Factory Girl 有没有简单的方法可以转换factories rb 文件中的所有yml 文件 我假设您想要做的是找到一个脚本来查看您的模型并为它们生成工厂 我尝试过一次 使用除了factory
  • 如何选择最大连接池大小?

  • 如何向彩色图像添加噪声 - Opencv

    我正在尝试向图像添加噪声 然后对其进行降噪以测试我的降噪算法 所以对于基准我指的是这个在线测试样品 我正在尝试复制噪声模型 参考这个线程1 2我正在像这样向图像添加噪点 Mat mSource Bgr mSource Bgr imread
  • 如何在二叉搜索树中迭代添加元素?

    public void Insert int value if value lt Data if LeftNode null LeftNode new TreeNode value else LeftNode Insert value el
  • build.gradle 中的 gradle 任务方法语法

    我是 gradle 和 groovy 的新手 我正在阅读 Gradle 的 usr 指南 并对任务方法有一些语法问题 task intro dependsOn hello doLast println I m Gradle 问题1 上面的代
  • Excel / VBA 通过交叉引用 2 个不同的工作表然后删除 1 行来删除重复行

    我有 2 个单独的工作表 我们称它们为工作表 A 工作表 B 我在工作表 B 中有数据 该数据也在工作表 A 中 我想找到那些相等的行并将它们从工作表 B 中删除 我无法合并两张表并使用过滤器 因为我正在执行动态 SQL 来查询不同的数据
  • 修改现有的通用存储库模式以添加选择

    我想修改现有的通用存储库以添加可选select类似于 Entity Framework Core 中的功能 期望的结果 private readonly IUnitOfWork unit without using select funct
  • htaccess,将所有请求重定向到 https://

    使用 htaccess 我需要重定向来自 https www domain to https domain 假设您在 Apache 配置中启用了 mod rewrite 则您的 htaccess 文件中将需要它 RewriteEngine
  • GCC 上 x86 intel asm 中方括号前的偏移量

    从我找到的所有文档中 没有提到类似的语法offset var offset2 采用 Intel x86 语法 但 GCC 具有以下标志 gcc S hello c o masm intel 对于这个程序 include
  • Spring Boot REST Api 中的一对多关系

    我正在使用 Spring Boot 创建 REST API 在此 API 中 我之间有一对多关系check in and Guests 我创建了一个用于签入的控制器并使用 spring JPA 的保存功能 保存方法正在更新两者checkin