You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改查询仅支持void/int/Integer返回类型报错及页面适配问题求助

Fixing java.lang.IllegalArgumentException for Modifying JPA Queries

The error you're hitting happens because Spring Data JPA's @Modifying queries only allow void or int/Integer as return types—they’re built for executing update/delete operations, not returning full entity objects. The conflict comes from your controller needing the updated Book object to power your Thymeleaf template. Here’s how to resolve this:

Step 1: Correct the Repository Method

First, update your repository method to return an Integer (this tells you how many rows were modified) instead of Book. Keep the @Modifying and @Transactional annotations intact:

@Transactional
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query(value = "update Book set reader_id=(select r.id from reader r where r.id_Number=:reader_id) where id=:book_id", nativeQuery = true)
Integer updateBookSetReaderId(Long reader_id, Long book_id);

Step 2: Fetch the Updated Book in the Controller

Since the modifying query doesn’t return the updated entity, you’ll need to explicitly fetch the latest state of the Book after running the update. This ensures your Thymeleaf template gets the valid, updated object it needs:

@GetMapping({"/searchreader","/searchreader{id}","/searchreader{id}/{book_id}"})
public String searchReaderById(@RequestParam("id") Optional<Long> id, @RequestParam("book_id") Optional<Long> book_id, Model model){
    if(id.isPresent()&&book_id.isPresent()){
        // Run the update first
        Integer updatedRowCount = bookRepository.updateBookSetReaderId(id.get(), book_id.get());
        
        // Only fetch the book if the update was successful
        if(updatedRowCount > 0) {
            Book updatedBook = bookRepository.findById(book_id.get()).orElse(null);
            model.addAttribute("givebook", updatedBook);
        } else {
            // Add an error message for invalid IDs or failed updates
            model.addAttribute("error", "Failed to update the book's reader. Check if the book or reader ID is valid.");
        }
        return "reader/searchreader";
    } else if(id.isPresent()) {
        Reader reader = readerService.findReaderByIdNumber(id.get());
        model.addAttribute("reader", reader);
        model.addAttribute("messages", readerService.getMessages());
        return "reader/searchreader";
    } else {
        return "reader/searchreader";
    }
}

Alternative: Use JPA Entity Operations (No Native SQL)

If you prefer a more object-oriented approach (and don’t need the raw performance of native SQL), you can skip @Modifying entirely:

  1. Update your repository to use standard JPA methods (if they don’t exist already):
Optional<Book> findById(Long id);
Book save(Book book);
  1. Adjust the controller logic to fetch, update, and save the book entity directly:
if(id.isPresent()&&book_id.isPresent()){
    Book book = bookRepository.findById(book_id.get()).orElse(null);
    if(book != null) {
        Reader reader = readerService.findReaderByIdNumber(id.get());
        book.setReader(reader); // Assuming your Book class has a setReader() method
        Book updatedBook = bookRepository.save(book);
        model.addAttribute("givebook", updatedBook);
    } else {
        model.addAttribute("error", "Book not found with the provided ID.");
    }
    return "reader/searchreader";
}

Which Approach Should You Pick?

  • Native SQL with @Modifying: Best for performance, especially if you’re updating multiple rows or have complex logic.
  • JPA Entity Operations: More readable, easier to maintain, and plays nicer with JPA’s caching and lifecycle events.

内容的提问来源于stack exchange,提问作者Victor Leunti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:24:05