CrudRepository findById 不返回 java.util。可选的

Zül*_*SIZ 4 java spring-data-jpa spring-boot

公共接口 LmsRepository 扩展了 CrudRepository 我没有 findOne 方法来获取单个计数,所以当我使用 findById 时,我得到了这个异常。“在类型 [java.util.Optional] 上找不到属性 [id]” 我该如何解决这个问题?

这是我的 CrudRepo

@Repository
public interface LmsRepository extends CrudRepository<Book, Long> {


}
Run Code Online (Sandbox Code Playgroud)

实体文件

@Entity(name="lms_tbl")
public class Book {

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

@Column(name="book_name")
private String bookName;

private String author;

@Column(name="purchase_date")
@Temporal(TemporalType.DATE)
private Date purchaseDate;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

and other....
Run Code Online (Sandbox Code Playgroud)

服务文件

@Service
public class LmsService {

@Autowired
private LmsRepository lmsRepository;

public Collection<Book> findAllBooks(){
    ArrayList<Book> books = new ArrayList<Book>();
    for (Book book : lmsRepository.findAll()) {
        books.add(book);
    }

    return books;
}

public void deleteBook(long id) {

    lmsRepository.deleteById(id);
}

public Optional<Book> findById(Long id) {

    return lmsRepository.findById(id);
}
Run Code Online (Sandbox Code Playgroud)

}

控制器文件

@Controller
public class MainController {

@Autowired
private LmsService lmsService;


@GetMapping("/")
public String index(HttpServletRequest req) {
    req.setAttribute("books", lmsService.findAllBooks());
    req.setAttribute("mode","BOOK_VIEW");
    return "index";
}

@GetMapping("/updateBook")
public String index(@RequestParam Long id,HttpServletRequest req) {
    req.setAttribute("book", lmsService.findById(id));
    req.setAttribute("mode","BOOK_EDIT");
    return "index";
}
Run Code Online (Sandbox Code Playgroud)

}

我尝试在 CrudRepo 中添加新方法,但它不起作用。

Lor*_*ore 7

在您的服务类中更改此

public Optional<Book> findById(Long id) {
    return lmsRepository.findById(id);
}
Run Code Online (Sandbox Code Playgroud)

对此

public Book findById(Long id) {
    return lmsRepository.findById(id).get();
}
Run Code Online (Sandbox Code Playgroud)

说明:Optional是一个包装类,它可能包含也可能不包含非空值。您收到该错误是因为您试图插入Optional模型,而不是Book. 由于Optional不包含任何id字段,您会收到错误消息。Optional当您有一个不希望它为空的空对象时,用于具有抛出异常的默认值。例如,您可以创建一个自动异常抛出,以防空可选。例如,您可以通过以下方式升级您的服务:

public Book findById(Long id) {
    return lmsRepository.findById(id).orElseThrow(RuntimeException::new);
}
Run Code Online (Sandbox Code Playgroud)

这将在 内抛出一个RuntimeExceptionany time Bookis null Optional,或者将返回Book该类的值。

更优雅的解决方案如下:

public Book findById(Long id) {
    return lmsRepository.findById(id).orElseThrow(NotFoundException::new);
}
Run Code Online (Sandbox Code Playgroud)

有:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException{
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,当可选包含 a 时Book,将返回给控制器并插入模型中。如果Optional包含空值,NotFoundException则将被抛出,它不需要被捕获,并将映射到 404 HTTP 错误。