GeneratedValue powoduje wyjątek InvalidDataAccessApiUsageException

1

Mam dwie przykładowe klasy połączone relacją wiele do wielu:

@Entity
@Table(name = "book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "book_category", joinColumns = {@JoinColumn(name = "book_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "category_id", referencedColumnName = "id")})
    private Set<Category> categories;
}
@Entity
@Table(name = "category")
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToMany(mappedBy = "categories", fetch = FetchType.LAZY)
    private List<Book> books;
}

Kiedy chciałbym dodać sobie jakąś książkę do bazy danych to otrzymuję wyjątek:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: dbTest.Category; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: dtTest.Category

Jeśli usunę adnotację @GeneratedValue z klasy Category to wszystko działa bez zarzutu. Może ktoś będzie wiedział jak to rozwiązać, żeby wszystko działało poprawnie?

0

A w jaki sposób dodajesz tą książkę?
Podeślij Kod

0

Rozszerzam JpaRespository a potem wywołuje metodę save()

public interface Repository extends JpaRepository<Book, Long>{
}
Repository repository;
// ...
repository.save(book);
0

Bardziej chodzi o otoczkę: czy twoje book ma ustawione id, czy category tego book maja ustawione id/istnieja na bazie, jak dodałeś category do book.

Zgaduję: zrobiłeś book.getCategories().add(category) a nie zrobiłeś category.getBooks().add(book) :p

0

Błąd mówi, że encja jest odczepiona od kontekstu.
Podrzuć kod, gdzie tworzysz obiekt book, w jaki sposób to robisz?

0

Jaka baza danych ?
@GeneratedValue(strategy = GenerationType.IDENTITY) obsługuje Oracle, DB2 i Postgres

0
public Book addBook(BookResource bookResource) {
        Book book = new Book();
       
        book.setTitle(bookResource.getTitle());
        book.setDescription(bookResource.getDescription());
        book.setCategories(Arrays.stream(bookResource.getCategories())
                .map(Category::new)
                .collect(Collectors.toSet()));

        return bookRepository.save(book);
    }

W klasie BookResource pole categories wygląda tak:

private Long[] categories;

Korzystam z bazy danych h2.

0

Coś dziwnego robisz z obiektami typu Category i hibernate uznaje je za obce. I nie pokazujesz tego kodu.

0

Skoro używasz h2 to spróbuj zmienić ten GeneratedValue na AUTO, albo na sequence

Przykład:

@Entity
public class EntityWithAutoId1 {
    @Id @GeneratedValue(strategy=GenerationType.AUTO) long id;
     
}

Sequence:

@Entity
// Define a sequence - might also be in another class:
@SequenceGenerator(name="seq", initialValue=1, allocationSize=100)
public class EntityWithSequenceId {
    // Use the sequence that is defined above:
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
    @Id long id;
}

0

Zmiana GeneratedValue na AUTO albo SEQUENCE nic nie daje.

Jednak dodanie adnotacji @Column(name = ...) przy polu id rozwiązało problem, tylko teraz hibernate nie może zmapować pola private Set<Category> categories;. Takie coś dostaje:

java.lang.IllegalStateException: Failed to load ApplicationContext

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unable to map collection com.github.model.Book.categories

Caused by: org.hibernate.AnnotationException: Unable to map collection com.github.model.Book.categories

Caused by: org.hibernate.cfg.RecoverableException: Unable to find column with logical name: id in org.hibernate.mapping.Table(book) and its related supertables and secondary tables

Caused by: org.hibernate.MappingException: Unable to find column with logical name: id in org.hibernate.mapping.Table(book) and its related supertables and secondary tables

No to poprawiłem w klasie Book w @JoinTable nazwę z id na book_id, ale wtedy dostaję:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FKAM8LLDERP40MVBBWCEQPU6L2S: PUBLIC.BOOK_CATEGORY FOREIGN KEY(CATEGORY_ID) REFERENCES PUBLIC.CATEGORY(CATEGORY_ID) (1)"; SQL statement:
insert into book_category (book_id, category_id) values (?, ?) [23506-196]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

Dodanie cascade = CascadeType.ALL w klasie Book sprawia, że wracamy do punktu wyjścia...

1 użytkowników online, w tym zalogowanych: 0, gości: 1