Home > Software design >  Getting 500 error when trying post method: PersistentObjectException: detached entity passed to pers
Getting 500 error when trying post method: PersistentObjectException: detached entity passed to pers

Time:08-15

I am trying to execute the POST method for adding a new sale. I have a one to many relationship with users to sales(one user to many sales). When trying to add a new sale, I am receiving an error PersistentObjectException: detached entity passed to persist: com.wiley.IndividualSalesTracker.entity.Sales.

Here's my User class:

package com.wiley.IndividualSalesTracker.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.List;
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")

    private Integer id;

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

    @OneToMany(mappedBy = "users", cascade = CascadeType.MERGE)
    @JsonIgnore
    private List<Sales> salesList;

    public User() {}

    public String getUserName(){
        return user_name;
    }
    public void setUserName(String user_name) {
        this.user_name = user_name;
    }

    public Integer getUserId() {
        return id;
    }
    public void setUserId(Integer user_id) {
        this.id = user_id;
    }

    public List<Sales> getSalesList() {
        return salesList;
    }
    public void setSalesList(List<Sales> salesList) {
        this.salesList = salesList;
    }


}

Here's my Sales class

package com.wiley.IndividualSalesTracker.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import java.util.List;

import javax.persistence.*;

@Entity
@Table(name = "sales")
public class Sales {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "policy_number", nullable = false)
    private Integer id;

//    @Column(name = "id")
//    private Integer userId;

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

    @Column(name = "premium")
    private Integer premium;

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

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

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

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

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

//    @OneToMany(mappedBy = "sales", cascade = CascadeType.MERGE)
//    @JsonIgnore
//    private List<Customer> customerList;

    @ManyToOne
    @JoinColumn(name = "id")
    private User users;

//    public Integer getUserId() {
//        return userId;
//    }
//
//    public void setUserId(Integer userId) {
//        this.userId = userId;
//    }


    public User getUsers() {
        return users;
    }
    public void setUsers(User users) {
        this.users = users;
    }

    public Integer getPolicyNumber() {
        return id;
    }

    public void setPolicyNumber(Integer policy_number) {this.id = policy_number;}

    public String getPolicyType() {
        return policy_type;
    }

    public void setPolicyType(String policy_type) {
        this.policy_type = policy_type;
    }

    public Integer getPremium() {
        return premium;
    }

    public void setPremium(Integer premium) {
        this.premium = premium;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getComments() {
        return comments;
    }

    public void setComments(String comments) {
        this.comments = comments;
    }

    public String getContactDate() {
        return contact_date;
    }

    public void setContactDate(String contact_date) {
        this.contact_date = contact_date;
    }

    public String getEffectiveDate() {
        return effective_date;
    }

    public void setEffectiveDate(String effective_date) {this.effective_date = effective_date;}

//    public List<Customer> getCustomerList() {
//        return customerList;
//    }
//    public void setCustomerList(List<Customer> customerList) {
//        this.customerList = customerList;
//    }
}

Sales Repository:

package com.wiley.IndividualSalesTracker.dao;

import com.wiley.IndividualSalesTracker.entity.Sales;
import org.hibernate.annotations.SQLDelete;

import javax.persistence.EntityManager;
import java.util.List;

public interface SalesRepository {

    void addSales(Sales sales);   //Create/Add sales
    List<Sales> getAllSales();     //Read/list all sales
    void updateSales(Sales sales);//Update sales
    void deleteSales(int userId);         //Delete one sales

    Sales getSalesByUserId(Integer userId);     //find sales by Id


    List<Sales> getAllPremiums(); // Gets all premiums from sales
    List<Sales> getAllAutoPolicies();
}

Sales Repository Implementation:

package com.wiley.IndividualSalesTracker.dao;

import com.wiley.IndividualSalesTracker.entity.Sales;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.List;

@Transactional
@Repository
public class SalesRepositoryImpl implements SalesRepository {

    @PersistenceContext
    private EntityManager em;

    @Override
    public void addSales(Sales sales) {
        em.persist(sales);
    }

    @Override
    public List<Sales> getAllSales() {
        String query = "select * from sales";
        return (List<Sales>) em.createNativeQuery(query).getResultList();
    }

    @Override
    public void deleteSales(int userId) {
        em.remove(getSalesByUserId(userId));
    }


    @Override
    public Sales getSalesByUserId(Integer userId) {
        return em.find(Sales.class, userId);
    }

    @Override
    public void updateSales(Sales sales) {
        Sales salesUpdate = getSalesByUserId(sales.getPolicyNumber());

        em.merge(sales);
        em.flush();
    }

    //   Lists all premiums from sales
    @Override
    public List<Sales> getAllPremiums() {
        String query = "SELECT premium from sales";
        return (List<Sales>) em.createNativeQuery(query).getResultList();
    }

    @Override
    public List<Sales> getAllAutoPolicies() {
        String query = "SELECT * FROM sales WHERE policyType WHERE = Auto";
        return (List<Sales>) em.createNativeQuery(query).getResultList();
    }

}

Sales Controller:

package com.wiley.IndividualSalesTracker.controller;

import com.wiley.IndividualSalesTracker.dao.SalesRepository;
import com.wiley.IndividualSalesTracker.entity.Sales;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/IndividualSalesTracker")
@CrossOrigin
public class IndividualSalesTrackerController {

    @Autowired
    private SalesRepository idsRepo;

    @GetMapping("/home")
    public ResponseEntity<List<Sales>> getAllSales() {
        List<Sales> mySales = idsRepo.getAllSales();
        return ResponseEntity.status(HttpStatus.OK).body(mySales);
    }

    @PostMapping()
    public ResponseEntity<Void> addSales(@RequestBody Sales sales) {
        idsRepo.addSales(sales);
        return new ResponseEntity<Void>(HttpStatus.CREATED);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Sales> getOneSale(@PathVariable("id") Integer id) {
        Sales sale = idsRepo.getSalesByUserId(id);
        return new ResponseEntity<Sales>(sale, HttpStatus.OK);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteOneSale(@PathVariable("userId") Integer id) {
        idsRepo.deleteSales(id);
        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
    }


    @PutMapping("/{id}")
    public ResponseEntity<Sales> updateOneSale(@PathVariable("userId") Integer id, @RequestBody Sales sales) {
        idsRepo.updateSales(sales);
        return new ResponseEntity<Sales>(sales, HttpStatus.OK);
    }

    @GetMapping("/premiums")
    public ResponseEntity<List<Sales>> getAllPremiums() {
        List<Sales> myPremiums = idsRepo.getAllPremiums();
        return ResponseEntity.status(HttpStatus.OK).body(myPremiums);
    }
    @GetMapping("/policyType/auto")
    public ResponseEntity<List<Sales>> getAllAutoPolicies() {
        List<Sales> myAutoPolicies = idsRepo.getAllAutoPolicies();
        return ResponseEntity.status(HttpStatus.OK).body(myAutoPolicies);
    }


}

And finally relevant DB info:

CREATE TABLE users (
    id INT(10) PRIMARY KEY AUTO_INCREMENT,
    user_name VARCHAR(45) NOT NULL UNIQUE
);


CREATE TABLE sales (
    id INT(10), 
    policy_number INT(7) PRIMARY KEY UNIQUE,
    policy_type VARCHAR(50),
    premium DECIMAL(6, 2),
    result VARCHAR(50) NOT NULL,
    reason VARCHAR(50),
    comments VARCHAR(50),
    contact_date VARCHAR(50),
    effective_date VARCHAR(50),
    FOREIGN KEY (id) REFERENCES users(id)
);

"detached entity passed to persist: com.wiley.IndividualSalesTracker.entity.Sales; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.wiley.IndividualSalesTracker.entity.Sales"

CodePudding user response:

Are you creating a new instance of your entity? I think your problem is that you are not working with a model/DTO of the data on your controller and you are directly trying to persist the "received" object. You can try to use a model of the data on your controller and create a new instance of the object you wanna save before of your call to the repository method. Regards.

CodePudding user response:

Fixed it, changed em.persist to em.merge. I also deleted @GeneratedValue(strategy = GenerationType.IDENTITY) from the sales class, since policy_number is not auto increment.

  • Related