简体   繁体   中英

java.lang.IllegalArgumentException: Invalid retrievedBook Id:1

While I trying delete Book entity with relations from database using this method

@Transactional
public void deleteBookById(Long id) {
   List<BookStatus> bookStatuses = bookStatusService.findBookStatusesByBookId(id);

   if (!bookStatuses.isEmpty()) {
        bookStatusService.deleteBookStatusesByBookId(id);
   }

   bookRepository.delete(findBookById(id));
}

I got an error
java.lang.IllegalArgumentException: Invalid retrievedBook Id:1 And here is more logs where you can see that this error appears exactly when I try do delete entity using hibernate

java.lang.IllegalArgumentException: Invalid retrievedBook Id:1
   at kpi.diploma.ovcharenko.service.book.LibraryBookService.lambda$findBookById$0(LibraryBookService.java:128) ~[classes/:na]
   at java.base/java.util.Optional.orElseThrow(Optional.java:408) ~[na:na]
   at kpi.diploma.ovcharenko.service.book.LibraryBookService.findBookById(LibraryBookService.java:128) ~[classes/:na]
   at kpi.diploma.ovcharenko.service.book.LibraryBookService.deleteBookById(LibraryBookService.java:64) ~[classes/:na]
   at kpi.diploma.ovcharenko.service.book.LibraryBookService$$FastClassBySpringCGLIB$$6c90428f.invoke(<generated>) ~[classes/:na]
   at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.10.jar:5.3.10]
   at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.10.jar:5.3.10]
   at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.10.jar:5.3.10]
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.10.jar:5.3.10]
   at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.10.jar:5.3.10]
   at kpi.diploma.ovcharenko.service.book.LibraryBookService$$EnhancerBySpringCGLIB$$e887da09.deleteBookById(<generated>) ~[classes/:na]
   at kpi.diploma.ovcharenko.controller.BookController.deleteBookById(BookController.java:155) ~[classes/:na]
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
   at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
   at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.10.jar:5.3.10]
   at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.10.jar:5.3.10]
   at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.10.jar:5.3.10]

But I have this entity in my database with such id, example below: 我存在的实体 Here is my Book entity class

@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "books")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idbooks", insertable = false, updatable = false, columnDefinition = "BINARY(16)")
    private Long id;

    @Column(name = "book_name")
    @NotBlank(message = "Book name is mandatory")
    private String bookName;

    @Column(name = "year")
    private int year;

    @Column(name = "author")
    private String author;

    @Column(name = "amount")
    private int amount;

    @Column(name = "description")
    private String description;

    @Column(name = "section")
    private String section;

    @OneToMany(mappedBy = "book", fetch = FetchType.EAGER)
    @EqualsAndHashCode.Exclude
    private Set<BookStatus> statuses = new HashSet<>();

    @EqualsAndHashCode.Exclude
    @OneToMany(mappedBy = "book", fetch = FetchType.EAGER)
    private Set<BookCategory> categories = new HashSet<>();

    @EqualsAndHashCode.Exclude
    @OnDelete(action = OnDeleteAction.CASCADE)
    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<BookCard> bookCards = new HashSet<>();

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE,
            })
    @JoinTable(
            name = "books_tags",
            joinColumns = {@JoinColumn(name = "book_id")},
            inverseJoinColumns = {@JoinColumn(name = "book_tag_id")}
    )
    Set<BookTag> tags = new HashSet<>();

    public void addCategory(BookCategory category) {
        categories.add(category);
        category.setBook(this);
    }

    public void removeCategory(BookCategory category) {
        categories.remove(category);
        category.setBook(null);
    }

    public void setStatus(BookStatus status) {
        statuses.add(status);
        status.setBook(this);
    }

    public Book(@NotBlank(message = "Book name is mandatory") String bookName, int year, String author,
                int amount, String description) {
        this.bookName = bookName;
        this.year = year;
        this.author = author;
        this.amount = amount;
        this.description = description;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return year == book.year && amount == book.amount && Objects.equals(id, book.id) && Objects.equals(bookName, book.bookName) && Objects.equals(author, book.author) && Objects.equals(description, book.description);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, bookName, year, author, amount, description);
    }
}

It's so strange error, but I even don't know what I can do to solve this problem.

here:

   bookRepository.delete(findBookById(id));

you are trying to pass findBookById(id) (which is of type Optional ) to the method delete, actually this method is waiting for a parameter of type Long and not Optional .

Try to delete the book by passing directly the id:

bookRepository.delete(id);

verify before that the id your are passing is of type Long.

List<BookStatus> bookStatuses = bookStatusService.findBookStatusesByBookId(id);

   if (!bookStatuses.isEmpty()) {
        bookStatusService.deleteBookStatusesByBookId(id);
   }

   bookRepository.delete(findBookById(id));

In your method above( deleteBookById ), you are retriving list of bookStatuses & if its non-empty, you are deleting it. Once it get deleted, you are again trying to delete it in last call bookRepository.delete(findBookById(id));.

May be this is your issue. Can you check if bookStatuses.isEmpty() condition is true & if deletion is happening prior to bookRepository.delete(findBookById(id)); call?

For the future people who also may face such a problem. I decided that this problem appears because of Hibernate problem, because I solved it in such way. Firstly a changed my Book entity class

@Getter
@Setter
@Entity
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "books")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idbooks", insertable = false, updatable = false)
    private Long id;

    @Column(name = "book_name")
    @NotBlank(message = "Book name is mandatory")
    private String bookName;

    @Column(name = "year")
    private int year;

    @Column(name = "author")
    private String author;

    @Column(name = "amount")
    private int amount;

    @Column(name = "description")
    private String description;

    @Column(name = "section")
    private String section;

    @EqualsAndHashCode.Exclude
    @OnDelete(action = OnDeleteAction.CASCADE)
    @OneToMany(mappedBy = "book", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<BookStatus> statuses = new HashSet<>();

    @EqualsAndHashCode.Exclude
    @OnDelete(action = OnDeleteAction.CASCADE)
    @OneToMany(mappedBy = "book", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<BookCategory> categories = new HashSet<>();

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToMany(mappedBy = "book", fetch = FetchType.EAGER, orphanRemoval = true)
    private Set<BookCard> bookCards = new HashSet<>();

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE,
            })
    @JoinTable(
            name = "books_tags",
            joinColumns = {@JoinColumn(name = "book_id")},
            inverseJoinColumns = {@JoinColumn(name = "book_tag_id")}
    )
    Set<BookTag> tags = new HashSet<>();

    public void addCategory(BookCategory category) {
        categories.add(category);
        category.setBook(this);
    }

    public void removeCategory(BookCategory category) {
        categories.remove(category);
        category.setBook(null);
    }

    public void addStatus(BookStatus status) {
        statuses.add(status);
        status.setBook(this);
    }

    public Book(@NotBlank(message = "Book name is mandatory") String bookName, int year, String author,
                int amount, String description) {
        this.bookName = bookName;
        this.year = year;
        this.author = author;
        this.amount = amount;
        this.description = description;
    }
}

After that I change default Hibernate method deleteById() to this in my BookRepository interface

@Modifying
@Transactional
@Query(value = "DELETE FROM Book b WHERE b.id = :id")
void deleteBookById(@Param("id") Long id);

In my BookService method deleteBookId() I remove deleting BookStatus because BookStatuses deletes cascadly when my book successfully deleted. And add method that delete all book cards by book id

@Override
@Transactional
public void deleteBookById(Long bookId) {
    bookCardService.deleteAllBookCardsByBookId(bookId);

    bookRepository.deleteBookById(bookId);
}

Here is deleteAllBookCardsByBookId in BookCard repository interface

@Modifying
@Query("delete from BookCard bc where bc.book.id = :id")
void deleteBookCardsByBookId(Long id);

And after all this changes I solved my problem and successfully delete book entity. I really hope that my solution to this problem in the future will be useful to anyone who encounters the same as me

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM