0

I am using Spring, Spring MVC, Spring Data, Hibernate, Maven I have seen similar question but the solutions didn't help me, so I decided to ask about it again. I have an application which should save a patient to doctor via a visit, but when I try add patient I got error. Thanks for help! Stacktrace:

Exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.virtualdent.entity.Visit; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.virtualdent.entity.Visit
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)


Root Cause
org.springframework.orm.jpa.JpaSystemException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.virtualdent.entity.Visit; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.virtualdent.entity.Visit
    org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:407)
    org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
    org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    com.sun.proxy.$Proxy50.save(Unknown Source)
    com.virtualdent.service.PatientServiceImpl.savePatient(PatientServiceImpl.java:32)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.base/java.lang.reflect.Method.invoke(Unknown Source)
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    com.sun.proxy.$Proxy61.savePatient(Unknown Source)
    com.virtualdent.controller.PatientController.savePatient(PatientController.java:71)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.base/java.lang.reflect.Method.invoke(Unknown Source)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

My entities:

@Entity
@Table
public class Visit implements Serializable {

    private static final long serialVersionUID = -135088128548004469L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Integer id;

    @Column
    private String day;

    @Column
    private String time;

    @ManyToMany(cascade={CascadeType.DETACH,CascadeType.PERSIST,CascadeType.REFRESH}, fetch=FetchType.EAGER)
    private List<Dentist>dentists;

    @OneToOne(mappedBy="visitDay",cascade= {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
    private Patient patient;

    public Visit() {}

    public Integer getId() {
        return id;
    }

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

    public String getDay() {
        return day;
    }

    public void setDay(String day) {
        this.day = day;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public List<Dentist> getDentists() {
        return dentists;
    }

    public void setDentists(List<Dentist> dentists) {
        this.dentists = dentists;
    }

    @Override
    public String toString() {
        return "Wizyta dnia: "+ day+" o godzinie:" + time;
    }

    public void addDentist(Dentist dentist)
    {
        if(dentists==null)
        {
            dentists=new ArrayList<>();
        }
        dentists.add(dentist);
    }

    public Patient getPatient() {
        return patient;
    }

    public void setPatient(Patient patient) {
        this.patient = patient;
    }
//standard hashcode and equals()    
}

@Entity
@Table
public class Patient {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Integer id;

    @OneToOne(cascade=CascadeType.ALL)
    private Visit visitDay;

    @Column
    private String firstName;

    @Column
    private String lastName;

    @Column
    private int number;

    @Column
    private String address;

    public Patient() {
        super();
    }

    public Integer getId() {
        return id;
    }

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

    public Visit getVisitDay() {
        return visitDay;
    }

    public void setVisitDay(Visit visitDay) {
        this.visitDay = visitDay;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
//standard hash code and equals()
}

@Entity
@Table(name="dentysta")
public class Dentist implements Serializable{

    private static final long serialVersionUID = 3128830699411486597L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Integer id;

    @Column
    private String firstName;

    @Column
    private String lastName;

    @Column
    private String specialization;

    @Column
    private int number;

    @Column
    private String address;


    @ManyToMany(mappedBy="dentists", cascade=CascadeType.ALL)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Visit>visits;

    public Dentist() {
    }

    public Integer getId() {
        return id;
    }

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

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getSpecialization() {
        return specialization;
    }

    public void setSpecialization(String specialization) {
        this.specialization = specialization;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<Visit> getVisits() {
        return visits;
    }

    public void setVisits(List<Visit> visits) {
        this.visits = visits;
    }


    public void addVisit(Visit visit)
    {
        if(visits==null)
        {
            visits=new ArrayList<>();
        }
        visit.addDentist(this);
        visits.add(visit);
    }

//standard hashcode and equals()
    }
}

My controller:

@Controller
@RequestMapping("/patient")
public class PatientController {

    @Autowired
    private DentistService dentistService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private VisitService visitService;


    @RequestMapping("/home")
    public String home(Model model)
    {
        List<Dentist>dentists=dentistService.getDentists();
        model.addAttribute("dentists",dentists);
        return "patient-home";
    }

    @RequestMapping("/showPatientForm")
    public String showForm(@RequestParam Integer id, Model model)
    {
        Dentist dentist=dentistService.getDentist(id);
        List<Visit>visits=dentist.getVisits();
        model.addAttribute("visits",visits);
        return "choose-visit-form";
    }

    @RequestMapping("/saveVisit")
    public String saveVisit(@RequestParam("visitId") Integer visitId,Model model)
    {
        Visit visit=visitService.getVisit(visitId);
        visitService.saveVisit(visit);
        model.addAttribute("patient",new Patient());
        model.addAttribute("visit",visit);
        return "patient-form";
    }


    @RequestMapping("/savePatient")
    public String savePatient(@RequestParam Integer visitId, @ModelAttribute("patient") Patient patient)
    {
        Visit visit=visitService.getVisit(visitId);
        patient.setVisitDay(visit);
        visit.setPatient(patient);

        patientService.savePatient(patient);
        return "redirect:/patient/home";
    }   
}  

my choose-visit-form.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1" isELIgnored="false"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>


<table border="1">

<tr>
<td>ID:</td>
<td>Day:</td>
<td>Time:</td>
<td>Action</td>
</tr>
<c:forEach items="${visits}" var="visit">
<tr>
<td>${visit.id}</td>
<td>${visit.day}</td>
<td>${visit.time}</td>
<td><a href="saveVisit?visitId=${visit.id}"> Zapisz </a></td>
</tr>

</c:forEach>
</table>
</body>
</html>

patient-form.jsp:


<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<div align="center">
<form:form action="savePatient?visitId=${visit.id}" modelAttribute="patient">

<table>
<tr>
<td>Imie: <form:input path="firstName"/></td>
</tr>

<tr>
<td>Nazwisko: <form:input path="lastName"/></td>
</tr>

<tr>
<td>Adres: <form:input path="address"/></td>
</tr>

<tr>
<td>Numer :<form:input path="number"/></td>
</tr>

<tr>
<td>
<input type="submit" value="Zapisz"/>
</td>
</tr>
</table>
</form:form>
</div>

</body>
</html>

my services:


@Service
@Transactional
public class PatientServiceImpl implements PatientService {

    @Autowired
    private PatientRepository repo;

    @Override
    public List<Patient> getPatients() {
        return repo.findAll();
    }

    @Override
    public Patient getPatient(Integer id) {
        return repo.findById(id).get();
    }

    @Override
    public void savePatient(Patient patient) {
        repo.save(patient);
    }

    @Override
    public void deletePatient(Integer id) {
        repo.deleteById(id);
    }

    @Override
    public List<Patient> search(String keyword) {
        // TODO Auto-generated method stub
        return null;
    }


@Service
@Transactional
public class VisitServiceImpl implements VisitService{

    @Autowired
    private VisitRepo visitRepo;

    @Override
    public List<Visit> getVisits() {
        return visitRepo.findAll();
    }

    @Override
    public List<Visit> getVisitsFromDentist(Integer id) {
        return visitRepo.findAllByDentistId(id);
    }

    @Override
    public Visit getVisit(Integer id) {
        return visitRepo.findById(id).get();
    }

    @Override
    public void saveVisit(Visit visit) {
        visitRepo.save(visit);
    }

    @Override
    public void deleteVisit(Integer id) {
        visitRepo.deleteById(id);
    }

    @Override
    public List<Visit> search(String keyword) {
        return null;
    }

}




kolo yolo
  • 23
  • 9
  • In which request method does the error occur? At what line? – Heri Dec 29 '19 at 15:06
  • the error occurs when i click submit in patient-form.jsp – kolo yolo Dec 29 '19 at 15:11
  • The error occurs on the server, not in the client. Use a debugger to investigate more. – Heri Dec 29 '19 at 15:12
  • It is my first time when I need to use debugger so sorry for my mistakes, but debugger says that in 56 line in patientController Visit visit=visitService.getVisit(visitId) i have a PersistentBag – kolo yolo Dec 29 '19 at 16:01
  • In PatientController line 68 the patient ID is null – kolo yolo Dec 29 '19 at 16:07
  • did you check the solution in https://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist – lakshman Dec 29 '19 at 16:34
  • Looking closer at your stacktrace: the call to PatientServiceImpl.savePatient occurs before the transaction mgmt comes into place. I assume you do not set the transaction scope (at least I do not see any annotations). Try to annotate your controller with @Transactional – Heri Dec 30 '19 at 08:25
  • @Heri I added Transactional to my controller but I still have the same error. I added my services to my post maybe something with them is wrong? – kolo yolo Dec 30 '19 at 13:15
  • @lakshman yeah i tried, but even if I delete bidirectional the error is the same – kolo yolo Dec 30 '19 at 13:17
  • Can you check value of visitId in saveVisit method of controller n also check the visitId exists in the database or not. – Anil Nivargi Dec 30 '19 at 13:29
  • Okay i found the source of problem. The problem disappear when In method savePatient in PatientController I added patient.setId(7) but I don't understand what does mean, beacause the number which i set in () is not matter, and the Id of patient are still set by hibernate. – kolo yolo Dec 30 '19 at 13:36
  • @Anil Nivargi yeah the visitId is in accordance with GeneratedType.SEQUENCE, the problem is that the patientId is not send to savePatient method. – kolo yolo Dec 30 '19 at 13:40

0 Answers0