I have AppUser that can have many BookCards, which can have many Books. I need to delete my AppUser with his BookCards entities, but no change for the book itself. But when I tried do it by this method
@Transactional
public void deleteUser(Long id) {
List<BookCard> bookCards = bookCardService.findAllUserBookCards(id);
if (!bookCards.isEmpty()) {
bookCardService.deleteBookCardByUserId(id);
}
userRepository.deleteById(id);
}
I got an error
org.hibernate.PropertyValueException: not-null property references a null or transient value : kpi.diploma.ovcharenko.entity.card.BookCard.book
This are my AppUser, Book And BookCard classes
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"), name = "library_user")
public class AppUser {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// other fields
@EqualsAndHashCode.Exclude
@OnDelete(action = OnDeleteAction.CASCADE)
@OneToMany(mappedBy = "book", fetch = FetchType.EAGER)
private Set<BookCard> bookCards = new HashSet<>();
// getters and setters
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "booking_card")
@TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
public class BookCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "user_id", nullable = false)
private AppUser user;
@OnDelete(action = OnDeleteAction.NO_ACTION)
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "book_id")
private Book book;
// getters and setters
@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)
private Long id;
// other fields
@EqualsAndHashCode.Exclude
@OnDelete(action = OnDeleteAction.NO_ACTION)
@OneToMany(mappedBy = "book", fetch = FetchType.EAGER)
private Set<BookCard> bookCards = new HashSet<>();
// getters and setters
As you can see, my Book class has field of Set bookCards, its just for understating that I tried to add many annotations, like @OnDelete(action = OnDeleteAction.CASCADE), believe that them can solve my problem
As I understand, its no problem with deleteting AppUser and his BookCard, but because BookCard has a relation to the Book, hibernate doesn't understand what to do with the Book. So how can I make it clear to my program that I just need to delete BookCards enetities, but do not touch the book itself? Thank you very much
CodePudding user response:
For the future readers, who can face a similar error. I solve my problem changing entities like this
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"), name = "library_user")
public class AppUser {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// other fields
@EqualsAndHashCode.Exclude
@OnDelete(action = OnDeleteAction.CASCADE)
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<BookCard> bookCards = new HashSet<>();
// getters and setters
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "booking_card")
@TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
public class BookCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", nullable = false)
private AppUser user;
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
@JoinColumn(name = "book_id")
private Book book;
// getters and setters
@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)
private Long id;
// other fields
@EqualsAndHashCode.Exclude
@OnDelete(action = OnDeleteAction.CASCADE)
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<BookCard> bookCards = new HashSet<>();
// getters and setters
This annotation solve this problem
org.hibernate.PropertyValueException: not-null property references a null or transient value : kpi.diploma.ovcharenko.entity.card.BookCard.book