使用Spring MVC ModelAndView编写具有多对一关系的类的控制器

问题描述

我正在开发一个Spring Boot Web应用程序,并且正在学习它。该应用程序用于管理/跟踪公司的硬件交易。用户可以创建新交易/新记录。在newRecord.jsp上,用户可以使用一种形式填写许多字段。然后,他们可以单击“保存”表单,然后将其重定向到newHardwareItems.jsp。本质上,每个newRecord可以具有多个硬件项目,因此newRecord与hardwareItems具有一对多的关系,而hardwareItems与newRecord具有多对一的关系,因为每个记录可以具有多个项目,但是许多项目属于一个记录。因此,一条记录的所有硬件项目都将显示在一页上,可以在该页上进行编辑,删除等。

因此,本质上,我的困惑通常在于如何编写NewRecordController和HardwareItemsController。这是因为我对如何处理控制器中它们之间的多对一/一对多关系感到困惑。首先,以下是仅显示双向关系的相关部分的实体:

@Entity
@Table(name="Records")
public class NewRecord extends Auditable<String>{

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="recordId")
    private Long recordId;


    @OnetoMany(mappedBy="record",cascade = {CascadeType.ALL})
    private List<HardwareItems> items;
...
}


@Entity
@Table(name="HardwareItems")
public class HardwareItems extends Auditable<String>{

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="item_id")
    private long itemId;
    
    @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name="record_id",nullable=false) 
    @OnDelete(action = OnDeleteAction.CASCADE)
    private NewRecord record;
    
    @Size(min=0,max=100,message="{hwItem.hwDescription.size}")
    @Column(name="hwDescription")
    private String hwDescription;
    @Size(min=0,message="{hwItem.hwSerialNumber.size}")
    @Column(name="hwSerialNumber")
    private String hwSerialNumber;
    @Size(min=0,message="{hwItem.hwModelNumber.size}")
    @Column(name="hwModelNumber")
    private String hwModelNumber;
...
}

如您所见,每个hwItem都有3个字段,用户将在newHardwareItems.jsp上填写这些字段。我的困惑在于如何为记录和硬件项目编写控制器。在意识到我需要硬件部件的此功能以及合并这种双向关系的复杂性之前,我已经使用了所有记录,但是现在一切对我来说都是乌云密布的。以下是页面的外观:

record

items

这很令人困惑,因为我必须弄清楚如何在一个表单提交中创建/删除/编辑/查看多个硬件项目,但我不确定该怎么做。我当时在考虑为每个项目(?)进行单独的表单提交,这很困难,因为那时我必须使用jQuery将所有人提交为不同的表单,而我也不知道该怎么做。因此,在这里您可以看到newHardwareItems.jsp文件

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<div class="panel-heading">
    <div class="panel-title"
        style="text-align: center; font-weight: bold; font-size: x-large; text-decoration: underline; margin: 1%;">Hardware
        Items</div>
</div>

<div class="outer">
    <div class="errors">
        <form:errors path="newRecord.*" />
        <form:errors path="message.*" />
        <form:errors path="hwItem.*" />
    </div>
</div>

<div class="form-style-5">
    <form:form modelattribute="item" id="form">
    
    <form:input type="hidden" path="dateCreated" />

        <div id="hwDetailsSection">

            <div class="outer">
                <input type="button" value="Add Hardware Item" id="hwAdditionButton">
            </div>

            <div id="hwAddition0">
                <input class="removeItemButton0" type="button" value="Remove Item"
                    id="removeItemButton" onclick="removeHWItem(this)"
                    style="display: inline-block;">
                <div class="form-row">
                    <div class="form-group col-md-4">
                        <label for="hwDescription" style="text-decoration: underline;">Description</label>
                        <form:textarea id="hwDescription" type="text"
                            class="form-control short" path="hwDescription"
                            name="hwDescription" placeholder="Description" maxlength="100"
                            rows="2" style="resize: none;" />
                    </div>
                    <div class="form-group col-md-4">
                        <label for="hwSerialNumber" style="text-decoration: underline;">Serial
                            #</label>
                        <form:input type="text" class="form-control" path="hwSerialNumber"
                            name="hwSerialNumber" placeholder="Serial #" maxlength="100" />
                    </div>
                    <div class="form-group col-md-4">
                        <label for="hwModelNumber" style="text-decoration: underline;">Model
                            #</label>
                        <form:input type="text" class="form-control" path="hwModelNumber"
                            name="hwModelNumber" placeholder="Model #" maxlength="100" />
                    </div>
                </div>
                <hr />
            </div>

        </div>

        <div class="outer">
            <input type="submit" name="submit" value="Save Items"
                id="addNewRecord" /> <input type="button" name="cancel"
                value=" Cancel " id="cancel" onclick="cancelClick()" />
        </div>

    </form:form>





    <!-- BOOTSTRAP FORM -->



</div>

<script
    src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>

    /******
    
    how to submit all forms on page using jQuery
    
    ******/

    function cancelClick() {
        if (confirm('Cancel Changes?')) {
            window.location.href = "/home";
        }
    }

    function removeHWItem(e) {

        var text = e.parentElement.id;

        count--;

        if (count == 0) {
            showHide();
            return;
        }

        e.parentElement.remove();
    }

    var count;

    $(function() {
        count = 0;
    });

    $('#hwAdditionButton').click(

            function() {

                if (count == 0) {

                    var clonedobj = $("#hwAddition" + count).clone().attr('id','hwAddition' + (count + 1));

                    clonedobj.find("#removeItemButton" + count).attr('id','removeItemButton' + (count + 1));

                    clonedobj.insertAfter("#hwAddition" + count);

                    count++;
                }

                else {

                    var clonedobj = $("#hwAddition" + (count - 1)).clone()
                            .attr('id','hwAddition' + count);

                    clonedobj.find("#removeItemButton" + (count - 1)).attr(
                            'id','removeItemButton' + count);

                    clonedobj.insertAfter("#hwAddition" + (count - 1));
                }

                count++;

            });
</script>

最后,现在是控制器,它们现在基本上是彼此的镜像,因为我不确定如何在它们之间建立双向关系。

package bcoreHW.controllers;

import java.util.Optional;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.modelattribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import bcoreHW.model.NewRecord;
import bcoreHW.model.NewRecordRepo;
import bcoreHW.model.UserRepo;
import bcoreHW.service.NewRecordService;
import bcoreHW.service.UserService;

@Controller
public class NewRecordController {
    
    @Autowired
    private NewRecordService newRecordService;
    
    @Autowired
    UserService userService;
    
    @Autowired UserRepo userRepo;
    
    @RequestMapping(value= {"/home"},method=RequestMethod.GET)
    ModelAndView getRecordList(ModelAndView modelAndView,@RequestParam(name="p",defaultValue="1") int pageNumber) {
        
        Page<NewRecord> page = newRecordService.getPage(pageNumber);    
        
        modelAndView.getModel().put("page",page);
        
        modelAndView.setViewName("app.home");
        
        return modelAndView;
    }
    
    @RequestMapping(value="/newRecord",method=RequestMethod.GET)
    ModelAndView newRecordGet(ModelAndView modelAndView,@modelattribute(value="newRecord") NewRecord newRecord) {
        
        modelAndView.setViewName("app.newRecord");      
        
        NewRecord latestNewRecord = newRecordService.getLatest();
        
        modelAndView.getModel().put("latestNewRecord",latestNewRecord);
        
        return modelAndView;
    }
    
    @RequestMapping(value="/newRecord",method=RequestMethod.POST)
    ModelAndView newRecordPost(ModelAndView modelAndView,@modelattribute(value="newRecord")@Valid NewRecord newRecord,BindingResult result) {
        
        modelAndView.setViewName("app.newRecord");
        
        if(!result.hasErrors()) {
            newRecordService.save(newRecord);
            modelAndView.getModel().put("newRecord",new NewRecord());
            modelAndView.setViewName("app.newHardwareItems");
        }
        
        return modelAndView;
    }
    
    @RequestMapping(value="/deleteRecord",method=RequestMethod.GET)
    ModelAndView deleteRecord(ModelAndView modelAndView,@RequestParam(name="id") Long recordId) {
        
        newRecordService.delete(recordId);
        
        modelAndView.setViewName("redirect:/home");
        
        return modelAndView;
    }
    
    
    @RequestMapping(value="/editRecord",method=RequestMethod.GET)
    ModelAndView editRecordGet(ModelAndView modelAndView,@RequestParam(name="id") Long recordId) {
        
        NewRecord newRecord = newRecordService.get(recordId);
        
        modelAndView.getModel().put("newRecord",newRecord);
        
        modelAndView.setViewName("app.editRecord");
        
        return modelAndView;
    }
    
    @RequestMapping(value="/editRecord",method=RequestMethod.POST)
    ModelAndView editRecordPost(ModelAndView modelAndView,NewRecord newRecord,BindingResult result) {
        
        modelAndView.setViewName("app.editRecord");
        
        
        if(!result.hasErrors()) {
            newRecordService.save(newRecord);
            modelAndView.setViewName("app.editHardwareItems");
        }

        return modelAndView;
    }
    
    @RequestMapping(value="/viewRecord",method=RequestMethod.GET)
    ModelAndView veiwRecord(ModelAndView modelAndView,newRecord);
        
        modelAndView.setViewName("app.viewRecord");
        
        return modelAndView;
    }
}


package bcoreHW.controllers;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.modelattribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import bcoreHW.model.HardwareItems;
import bcoreHW.model.HardwareItemsRepo;
import bcoreHW.model.NewRecord;
import bcoreHW.service.HardwareItemsService;

@Controller
public class HwItemController {

    @Autowired
    private HardwareItemsService hwService;

    @Autowired
    private HardwareItemsRepo hwItemsRepo;

    @RequestMapping(value = "/newHardwareItems",method = RequestMethod.GET)
    ModelAndView newHwItemsGet(ModelAndView modelAndView,@modelattribute(value = "item") HardwareItems item) {

        modelAndView.setViewName("app.newHardwareItems");

        NewRecord record = item.getRecord();

        List<HardwareItems> items = hwItemsRepo.findByRecord(record.getRecordId());

        modelAndView.getModel().put("items",items);

        return modelAndView;
    }

    @RequestMapping(value = "/newHardwareItems",method = RequestMethod.POST)
    ModelAndView newHwItemsPost(ModelAndView modelAndView,@modelattribute(value = "item") @Valid HardwareItems item,BindingResult result) {

        modelAndView.setViewName("app.newHardwareItems");

        if (!result.hasErrors()) {
            hwService.save(item);
            modelAndView.getModel().put("item",new HardwareItems());
            modelAndView.setViewName("redirect:/home");
        }

        return modelAndView;
    }

    @RequestMapping(value = "/editHardwareItems",method = RequestMethod.GET)
    ModelAndView editHwItemsGet(ModelAndView modelAndView,@RequestParam(value = "itemId") Long itemId,BindingResult result) {

        HardwareItems item = hwService.get(itemId);
        modelAndView.getModel().put("item",item);
        modelAndView.setViewName("app.editHardwareItems");

        return modelAndView;
    }

    @RequestMapping(value = "/editHardwareItems",method = RequestMethod.POST)
    ModelAndView editHwItemsPost(ModelAndView modelAndView,BindingResult result) {

        modelAndView.setViewName("app.editHardwareItems");

        if (!result.hasErrors()) {
            hwService.save(item);
            modelAndView.setViewName("redirect:/home");
        }

        return modelAndView;
    }

    @RequestMapping(value = "/deleteHardwareItems",method = RequestMethod.GET)
    ModelAndView deleteHwItems(ModelAndView modelAndView,@RequestParam(name = "itemId") Long itemId) {

        hwService.delete(itemId);

        modelAndView.setViewName("redirect:/home");

        return modelAndView;
    }

}

我基本上在将创建的每个硬件项目连接到单个记录时遇到麻烦。我不知道在哪里/何时/如何为每个项目设置记录。因此,基本上,我对记录和硬件项目都有3个视图,分别是“新”,“编辑”和“视图”,其中每个硬件项目视图必须正确地与关联的记录一起显示。但是现在,由于不确定如何通过这种关系设置端点,因此我不确定如何设置端点。

任何有关此方面的见解将不胜感激。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)