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.