简体   繁体   中英

Spring boot JPA: How to keep the child entity when deleting the parent entity in a many-to-one relationship?

I'm new to the Spring boot JPA and struggling to find out the relationships between multiple entities.

I have a User Entity, a Product Entity, and a Review Entity. A user has many reviews. A product has many reviews. A review has a product and a user.

At the moment, I'm using one-to-many relationships for user&reivew, product&review. However, the error occurred when deleting a review: ERROR: update or delete on table "users" violates foreign key constraint "fkcgy7qjc1r99dp117y9en6lxye" on table "reviews".

My question:

  1. How can I delete a Review Entity without deleting the Product entity and User entity?
  2. Which cascade type should I use?

User Entity:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "user_name")
    private String userName;
    @Column(name = "email")
    private String email;
    @Column(name = "password")
    private String password;


    @JsonManagedReference("reviews")
    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY,
            mappedBy = "user")
    private List<Review> reviews = new ArrayList<>();
//constructor + getter+ setter

Product Entity:

@Entity
@Table(name = "products")
public class Product {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Float price;
    @Transient
    private Float rate;

    private String category;
    private String brand;


    @JsonManagedReference("reviews")
    @JsonIgnore
    @OneToMany(mappedBy = "product")
    List<Review> reviews = new ArrayList<>();
//constructor + getter+ setter

Review Entity:

@Entity
@Table(name = "reviews")
public class Review {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Float rate;
    private String comment;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    @JsonBackReference("user")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JsonBackReference("product")
    @JoinColumn(name = "product_id",referencedColumnName = "id")
    private Product product;
//constructor + getter+ setter

User Controller:

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping(path="users/")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    ...
    @DeleteMapping("{userid}")
    public User deleteUser(@PathVariable("userid") Long userid){
        return userService.deleteById(userid);
    }
}

User service:

@Service
public class UserService {
    private final UserRepository userRepository;
    private final ReviewRepository reviewRepository;
    //dependency injection
    @Autowired
    public UserService(UserRepository userRepository, ReviewRepository reviewRepository) {
        this.userRepository = userRepository;
        this.reviewRepository =reviewRepository;
    }

   ...
    public User getUserById(Long id){
        return userRepository.findById(id).orElseThrow(()->
                new UserNotFoundException(id));
    }
    public User deleteById(Long id){
        User user = getUserById(id);
        userRepository.delete(user);
        return user;
    }

}

Simple run:

@SpringBootApplication
public class GroceryShoppingAppApplication  {

    public static void main(String[] args) {
        ConfigurableApplicationContext configurableApplicationContext =
                SpringApplication.run(GroceryShoppingAppApplication.class, args);

        UserRepository userRepository = configurableApplicationContext.getBean(UserRepository.class);
        ProductRepository productRepository =configurableApplicationContext.getBean(ProductRepository.class);
        ReviewRepository reviewRepository = configurableApplicationContext.getBean(ReviewRepository.class);

        User debbi= new User("Debbi","debbi@gamil.com","password");

        Product apple = new Product("Apple",(float)3.40,"Fruit","Gala");
        Product milk = new Product("Milk",(float)5.22,"Dairy","Anchor");

        Review review1 = new Review(debbi,(float)4.5,"Good taste",apple);
        Review review2 = new Review(debbi,(float)5.0,"Good milk",milk);

        productRepository.save(apple);
        productRepository.save(milk);

        userRepository.save(debbi);

        reviewRepository.save(review1);
        reviewRepository.save(review2);

I think I should not use casacadeType.All because when deleting a user, I shouldn't delete the product in the review. I tried other types, the error still remains. Thus, currently I didn't use any casacadeType and need to save each entity one by one.

Please help me with this.

You are getting an error because the user in the review model does not have a referenced Column value.

Try this code:

@JoinColumn(name = "user_id",referencedColumnName = "id")

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