首页 > 解决方案 > Spring Boot findbyid 返回可选错误

问题描述

你好朋友我正在用 Thymeleaf 创建一个图书馆管理应用程序,我已经映射了关系并创建了一些关系,并且多对多的关系正在工作,例如你将注册一本书(只有名称),然后它将有一个链接命名详细信息,您将能够在其中完成注册并选择作者和主题,两者都是多对多关系及其工作

图书注册详细信息显示一本已创建的图书 在此处输入图像描述

现在我的问题是多对一关系,它的工作方式相同,您将创建一个图书馆,然后在详细信息中您将能够将书籍添加到该图书馆

在此处输入图像描述

在此处输入图像描述

在我正在创建的项目中,一个图书馆可以有多本书,但一本书只能在一个图书馆中,这是该图书馆独有的,当我尝试添加这本书并提交时,我收到一条错误消息:

不存在值 java.util.NoSuchElementException:java.base/java.util.Optional.get 中不存在值(Optional.java:141)

我试图解决这个问题几个小时,我的猜测是控制器无法找到 Book id,但我不知道为什么......

这是我上面的代码: Ps:我知道我有工作要做,创建 DTO 并使其更清洁,我只想让它先工作

这里的图书馆控制器是我试图在 ediLib 方法中添加创建的书的地方

package com.msoftwares.librarymanager.controller;

import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import com.msoftwares.librarymanager.models.Services.BookService;
import com.msoftwares.librarymanager.models.Services.LibraryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import java.util.List;

@RestController
@RequestMapping(path ="/api/library")
public class LibraryController {

    @Autowired
    LibraryService libraryService;

    @Autowired
    BookService bookService;




    @GetMapping(path = "/all")
    public ModelAndView getLibraries(){
        ModelAndView modelAndView = new ModelAndView("libraryTemplate");
        modelAndView.addObject("newLibrary", new Library());
        modelAndView.addObject("getLibraries", libraryService.getLibrary());
        return modelAndView;
    }

    @GetMapping(path = "/details/{id}")
    public ModelAndView getDetails(@PathVariable("id") Integer id){
        Library library = libraryService.findLibById(id);
        ModelAndView modelAndView = new ModelAndView("libraryEdit");
        modelAndView.addObject("library", library );
        List<Book> unselectedBooks = bookService.getBooks();
        unselectedBooks.removeAll(library.getBook());
        modelAndView.addObject("availableBooks", unselectedBooks);
        return modelAndView;
    }

    @PostMapping(path = "/editLib")
    public RedirectView editLib(@ModelAttribute Book book, @RequestParam Integer libId){
        Library library = libraryService.findLibById(libId);
        book = bookService.getBookById(book.getIsbn());
        libraryService.saveLibrary(library);


        return new RedirectView("http://localhost:8080/api/library/details/" + libId);
    }

    @PostMapping(path = "/create")
    public RedirectView createLibrary(@ModelAttribute Library library){
        libraryService.saveLibrary(library);
        return new RedirectView("http://localhost:8080/api/library/all");
    }


}

图书控制器

package com.msoftwares.librarymanager.controller;

import com.msoftwares.librarymanager.models.Entities.Author;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.BookTheme;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.AuthorRepository;
import com.msoftwares.librarymanager.models.Repo.BookRepository;
import com.msoftwares.librarymanager.models.Repo.BookThemeRepository;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import com.msoftwares.librarymanager.models.Services.AuthorService;
import com.msoftwares.librarymanager.models.Services.BookService;
import com.msoftwares.librarymanager.models.Services.BookThemeService;
import com.msoftwares.librarymanager.models.Services.LibraryService;
import org.dom4j.rule.Mode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import javax.swing.text.html.HTML;
import java.util.List;

@RestController
@RequestMapping(path ="/api/books")
public class BookController {

    @Autowired
    BookService bookService;

    @Autowired
    AuthorService authorService;

    @Autowired
    BookThemeService bookThemeService;

    //get all books
    @GetMapping(path = "/all")
    public ModelAndView getBooks(){
        ModelAndView modelAndView = new ModelAndView("booksTemplate");
        modelAndView.addObject("newBook", new Book());
        modelAndView.addObject("getAuthors", authorService.getAuthors());
        modelAndView.addObject("getBooks", bookService.getBooks());
        modelAndView.addObject("getThemes", bookThemeService.getThemes());
        return modelAndView;
    }

    //create book
    @PostMapping(path = "/create")
    public RedirectView createBook(@ModelAttribute Book book) {
        bookService.saveBook(book);
        return new RedirectView("http://localhost:8080/api/books/all");
    }

    //get details
    @GetMapping(path = "/details/{id}")
    public ModelAndView getDetails(@PathVariable("id") Integer id){
        Book book = bookService.getBookById(id);
        ModelAndView modelAndView = new ModelAndView("bookDetails");
        modelAndView.addObject("bookId", book);
        List<Author> unselectedAuthors = authorService.getAuthors();
        List<BookTheme> unselectedBookThemes = bookThemeService.getThemes();
        unselectedAuthors.removeAll(book.getAuthors());
        unselectedBookThemes.removeAll(book.getBookThemes());
        modelAndView.addObject("authors", unselectedAuthors);
        modelAndView.addObject("bookThemes", unselectedBookThemes);

        return modelAndView;
    }

    //register authors
    @PostMapping(path = "/registerDetails")
    public RedirectView registerDetails(@ModelAttribute Author author, @RequestParam Integer isbn){
        Book book = bookService.getBookById(isbn);
        author = authorService.getAuthorById(author.getId());

        book.getAuthors().add(author);

        bookService.saveBook(book);
        return new RedirectView("http://localhost:8080/api/books/details/" + isbn);
    }

    //register themes
    @PostMapping(path = "/registerTheme")
    public RedirectView registerThemes(@ModelAttribute BookTheme bookTheme, @RequestParam Integer isbn){
        Book book = bookService.getBookById(isbn);
        bookTheme = bookThemeService.getThemeById(bookTheme.getId());

        book.getBookThemes().add(bookTheme);
        bookService.saveBook(book);
        return new RedirectView("http://localhost:8080/api/books/details/" + isbn);
    }



}

图书馆服务

package com.msoftwares.librarymanager.models.Services;

import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LibraryService {

    @Autowired
    LibraryRepository libraryRepository;

    @Autowired
    BookService bookService;


    //get all
    public List<Library> getLibrary(){return libraryRepository.findAll();}

    //get by id
    public Library findLibById(int id){return libraryRepository.findById(id).get();}

    //save
    public void saveLibrary(Library library){libraryRepository.save(library);}

    //delete
    public void deleteLibrary(Library library){libraryRepository.delete(library);}

    

}

图书服务(finById 方法所在的位置)

package com.msoftwares.librarymanager.models.Services;

import com.msoftwares.librarymanager.models.Entities.Author;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Repo.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class BookService {

    @Autowired
    BookRepository bookRepository;

    //get all books
    public List<Book> getBooks(){
        return bookRepository.findAll();
    }

    //save book
    public void saveBook(Book book){
        bookRepository.save(book);
    }

    //find books by id
    public Book getBookById(int id){
        return bookRepository.findById(id).get();
    }

    //delete
    public void deleteBook(Book book){
        bookRepository.delete(book);
    }



}

图书馆实体

package com.msoftwares.librarymanager.models.Entities;

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

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Library {

    public Library(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

    @Column
    private String name;

    @Column
    private String address;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Client> clients = new ArrayList<>();

    @OneToMany
    private List<Book> book = new ArrayList<>();


}

图书实体

package com.msoftwares.librarymanager.models.Entities;

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

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Book {

    public Book(String title) {
        this.title = title;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int isbn;

    @Column
    private String title;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Author> authors = new ArrayList<>();

    @ManyToMany(fetch = FetchType.LAZY)
    private List<BookTheme> bookThemes = new ArrayList<>();

    @ManyToOne
    private Library library;


}

我看到 findById 方法。它来自一个可选接口,它检查它是否有值,但是 id 在我的数据库中,他只是无法找到 id,我尝试在 Book 上建立关系控制器,它工作,但在图书馆控制器它没有。

标签: javaspringspring-bootspring-mvcspring-data-jpa

解决方案


检查您的代码后,您的问题出在您的 thymeleaf 模板中。

库编辑.html

<form th:action="@{/api/library/editLib/(libId=${library.id})}" method="post">
        <label><b> Select Books</b></label>
        <select name="id" required>
            <option value="">Choose books</option>
            <option th:each="book : ${availableBooks}"
                    th:value="${book.isbn}"
                    th:text="${book.title}">
            </option>
        </select>
        <input type="submit" value="Save" />
    </form>

您必须使用isbn更改id

        <select name="isbn" required>

因为您的实体 Book的 ID 为isbn :

public class Book {
    //...

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int isbn;

    // ...

您对此感到困惑,因为例如 bookDetails.html,您可以毫无问题地使用“id”作为作者和主题,因为

 <select name="id" required>

他们的实体同时拥有

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

要了解有关 ModelAttribute 如何工作的更多信息,请参阅此链接


推荐阅读