I'm currently stuck on some point in Spring. Currently, I have 2 tables, named Patient and Risk, joined by a table called Riskpatient. Whenever I try to delete a Risk object from a Patient instance, it does not seem to delete the object from the list. This is the setup:
package medicapp.models.impl;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
@Entity
@Table(name="patient")
public class Patient {
@Id
@GeneratedValue
@Column(name="Id")
private int id;
@Column(name="NatNumber")
private String nationalNumber;
@Column(name="FirstName")
private String firstName;
@Column(name="LastName")
private String lastName;
@Column(name="Address")
private String address;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="birthplace")
private Municipality birthPlace;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="zipcode")
private Municipality municipality;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="healthinsuranceid")
private HealthInsurance healthInsurance;
@Column(name="Nationality")
private String nationality;
@Column(name="ContactName")
private String contactName;
@Column(name="ContactNumber")
private String contactNumber;
@Column(name="Phone")
private String phone;
@Column(name="Email")
private String email;
@Column(name="Gender")
private Character gender;
@Column(name="DateOfBirth")
@Temporal(TemporalType.DATE)
private Date birthDate;
@Column(name="Smoker")
private boolean smoker;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="bloodgroupid")
private BloodType bloodType;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="juridicalid")
private Juridical juridical;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "allergypatient",
joinColumns={@JoinColumn(name="PatientId")},
inverseJoinColumns={@JoinColumn(name="AllergyId")}
)
@JsonIgnore
private List<Allergy> allergies;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "medicationpatient",
joinColumns = @JoinColumn(name="PatientId"),
inverseJoinColumns = @JoinColumn(name = "MedicationId")
)
@JsonIgnore
private List<Medication> medications;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "chronicdiseasepatient",
joinColumns = @JoinColumn(name="PatientId"),
inverseJoinColumns = @JoinColumn(name = "ChronicDiseaseId")
)
@JsonIgnore
private List<Disease> diseases;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "vaccinationpatient",
joinColumns = @JoinColumn(name="PatientId"),
inverseJoinColumns = @JoinColumn(name = "VaccinationId")
)
@JsonIgnore
private List<Vaccination> vaccinations;
@ManyToMany//set to eager to solve hibernate exception: collection is not associated with any session
@JoinTable(name = "riskpatient",
joinColumns = @JoinColumn(name="PatientId"),
inverseJoinColumns = @JoinColumn(name = "RiskId")
)
private List<Risk> risks;
@Column(name="lastwill")
private boolean lastWill;
/**
* Default Constructor without parameters, this is required for using Hibernate
*/
public Patient() {
}
/**
* Constructor used to manually make a new patient with the minimal required values
* @param firstName The first name of the patient
* @param lastName The last name of the patient
* @param address The address of the patient
* @param municipality The municipality of the patient
* @param birthDate The birthdate of the patient
*/
public Patient(String firstName, String lastName, String address, Municipality municipality, Date birthDate) {
this.firstName = firstName;
this.address = address;
this.municipality = municipality;
this.lastName = lastName;
this.lastName = lastName;
this.birthDate = birthDate;
}
/**
* Patient constructor that uses all the values retrieved from the e-ID
* @param firstName The first name of the patient
* @param lastName The last name of the patient
* @param address The address of the patient
* @param municipality The municipality of the patient
* @param birthPlace The birthplace of the patient
* @param nationalNumber The nationalnumber of the patient
* @param nationality The nationality of the patient
* @param gender The gender of the patient
* @param birthDate The birthdate of the patient
* @author Geert Peters
*/
public Patient(String firstName, String lastName, String address, Municipality municipality, Municipality birthPlace, String nationalNumber, String nationality, char gender, Date birthDate) {
this.address = address;
this.birthDate = birthDate;
this.birthPlace = birthPlace;
this.firstName = firstName;
this.gender = gender;
this.lastName = lastName;
this.nationality = nationality;
this.nationalNumber = nationalNumber;
this.municipality = municipality;
}
/**
* @param allergy adds an allergy to a patient's file
*/
public void addAllergy(Allergy allergy) {
this.allergies.add(allergy);
}
/**
* @param disease adds a disease to a patient's file
*/
public void addDisease(Disease disease) {
this.diseases.add(disease);
}
/**
* @param medication adds a medication to a patient's file
*/
public void addMedication(Medication medication) {
this.medications.add(medication);
}
/**
* @param vaccination adds a vaccination to a patient's file
*/
public void addVaccination(Vaccination vaccination) {
this.vaccinations.add(vaccination);
}
/**
* @param medication removes a medication from the list
*/
public void removeMedication(Medication medication) {
this.medications.remove(medication);
}
/**
* Gets smoker.
*
* @return Value of smoker.
*/
public boolean isSmoker() {
return smoker;
}
/**
* Gets birthPlace.
*
* @return Value of birthPlace.
*/
public Municipality getBirthPlace() {
return birthPlace;
}
/**
* Sets new id.
*
* @param id New value of id.
*/
public void setId(int id) {
this.id = id;
}
/**
* Sets new smoker.
*
* @param smoker New value of smoker.
*/
public void setSmoker(boolean smoker) {
this.smoker = smoker;
}
/**
* Gets id.
*
* @return Value of id.
*/
public int getId() {
return id;
}
/**
* Gets address.
*
* @return Value of address.
*/
public String getAddress() {
return address;
}
/**
* Sets new lastName.
*
* @param lastName New value of lastName.
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* Gets gender.
*
* @return Value of gender.
*/
public char getGender() {
return gender;
}
/**
* Gets nationalNumber.
*
* @return Value of nationalNumber.
*/
public String getNationalNumber() {
return nationalNumber;
}
/**
* Gets firstName.
*
* @return Value of firstName.
*/
public String getFirstName() {
return firstName;
}
/**
* Gets municipality.
*
* @return Value of municipality.
*/
public Municipality getMunicipality() {
return municipality;
}
/**
* Sets new nationalNumber.
*
* @param nationalNumber New value of nationalNumber.
*/
public void setNationalNumber(String nationalNumber) {
this.nationalNumber = nationalNumber;
}
/**
* Sets new nationality.
*
* @param nationality New value of nationality.
*/
public void setNationality(String nationality) {
this.nationality = nationality;
}
/**
* Sets new municipality.
*
* @param municipality New value of municipality.
*/
public void setMunicipality(Municipality municipality) {
this.municipality = municipality;
}
/**
* Gets phone.
*
* @return Value of phone.
*/
public String getPhone() {
return phone;
}
/**
* Sets new gender.
*
* @param gender New value of gender.
*/
public void setGender(char gender) {
this.gender = gender;
}
/**
* Gets contactNumber.
*
* @return Value of contactNumber.
*/
public String getContactNumber() {
return contactNumber;
}
/**
* Gets lastName.
*
* @return Value of lastName.
*/
public String getLastName() {
return lastName;
}
/**
* Sets new address.
*
* @param address New value of address.
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Sets new firstName.
*
* @param firstName New value of firstName.
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* Sets new birthPlace.
*
* @param birthPlace New value of birthPlace.
*/
public void setBirthPlace(Municipality birthPlace) {
this.birthPlace = birthPlace;
}
/**
* Gets nationality.
*
* @return Value of nationality.
*/
public String getNationality() {
return nationality;
}
/**
* Gets contactName.
*
* @return Value of contactName.
*/
public String getContactName() {
return contactName;
}
/**
* Gets birthDate.
*
* @return Value of birthDate.
*/
public Date getBirthDate() {
return birthDate;
}
/**
* Sets new contactName.
*
* @param contactName New value of contactName.
*/
public void setContactName(String contactName) {
this.contactName = contactName;
}
/**
* Sets new phone.
*
* @param phone New value of phone.
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* Sets new contactNumber.
*
* @param contactNumber New value of contactNumber.
*/
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
/**
* Sets new birthDate.
*
* @param birthDate New value of birthDate.
*/
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
/**
* Gets vaccinations.
*
* @return Value of vaccinations.
*/
public List<Vaccination> getVaccinations() {
return vaccinations;
}
/**
* Gets allergies.
*
* @return Value(Set) of allergies.
*/
public List<Allergy> getAllergies() {
return allergies;
}
/**
* Gets diseases.
*
* @return Value(List) of diseases.
*/
public List<Disease> getDiseases() {
return diseases;
}
/**
* Gets medications.
*
* @return Value(List) of medications.
*/
public List<Medication> getMedications() {
return medications;
}
/**
* Gets bloodgroup.
*
* @return Value of bloodgroup.
*/
public BloodType getBloodType() {
return bloodType;
}
/**
* Sets new bloodgroup.
*
* @param bloodType New value of bloodgroup.
*/
public void setBloodType(BloodType bloodType) {
this.bloodType = bloodType;
}
/**
* Gets HealthInsurance.
*
* @return Value of HealthInsureance.
*/
public HealthInsurance getHealthInsurance() {
return healthInsurance;
}
/**
* Sets new HealthInsurance.
*
* @param healthInsurance New value of HealthInsurance.
*/
public void setHealthInsurance(HealthInsurance healthInsurance) {
this.healthInsurance = healthInsurance;
}
/**
* Gets email.
*
* @return Value of email.
*/
public String getEmail() {
return email;
}
/**
* Sets new lastWill.
*
* @param lastWill New value of lastWill.
*/
public void setLastWill(boolean lastWill) {
this.lastWill = lastWill;
}
/**
* Sets new juridical.
*
* @param juridical New value of juridical.
*/
public void setJuridical(Juridical juridical) {
this.juridical = juridical;
}
/**
* Sets new allergies.
*
* @param allergies New value of allergies.
*/
public void setAllergies(List<Allergy> allergies) {
this.allergies = allergies;
}
/**
* Sets new diseases.
*
* @param diseases New value of diseases.
*/
public void setDiseases(List<Disease> diseases) {
this.diseases = diseases;
}
/**
* Gets lastWill.
*
* @return Value of lastWill.
*/
public boolean isLastWill() {
return lastWill;
}
/**
* Gets juridical.
*
* @return Value of juridical.
*/
public Juridical getJuridical() {
return juridical;
}
/**
* Sets new medications.
*
* @param medications New value of medications.
*/
public void setMedications(List<Medication> medications) {
this.medications = medications;
}
/**
* Sets new email.
*
* @param email New value of email.
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Sets new vaccinations.
*
* @param vaccinations New value of vaccinations.
*/
public void setVaccinations(List<Vaccination> vaccinations) {
this.vaccinations = vaccinations;
}
/**
* Sets new Risks
* @param risks New value of risks
*/
public void setRisks(List<Risk> risks) {
this.risks = risks;
}
/**
* Gets all the risks bound to the patient
* @return a {@link java.util.List} instance containing all the risks of the patient
*/
public List<Risk> getRisks() {
return risks;
}
}
package medicapp.models.impl;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name="risk")
public class Risk {
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="description")
private String description;
/** @ManyToMany(mappedBy = "risks")
private List<Patient> patientList;*/
public Risk() {
}
public Risk(String description) {
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<import resource="spring-database.xml"/>
<import resource="spring-security.xml"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="medicapp" />
<property name="dataSource" ref="dataSource" />
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
</bean>
<bean id="tm" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="emf" p:jpaDialect-ref="jpaDialect"/>
<tx:annotation-driven transaction-manager="tm"/>
<context:component-scan base-package="medicapp.*" />
<context:spring-configured />
<context:annotation-config />
<mvc:resources mapping="/resources/**" location="/resources/mytheme/" />
<mvc:annotation-driven/>
</beans>
My DAO implementation file:
@Override
@Transactional
public Patient deleteRiskOfPatient(Patient patient, Risk risk) {
try {
patient.getRisks().remove(risk);
// em.flush();
return patient;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getStackTrace());
}
return null;
}
The controller method which calls the DAO method:
@RequestMapping(method = RequestMethod.GET, value="/delete")
@Transactional
public void test() {
Patient patient = medicappDAO.getPatientById(6);
Hibernate.initialize(patient.getRisks());
System.out.println( patient.getRisks().size());
medicappDAO.deleteRiskOfPatient(medicappDAO.getPatientById(6), medicappDAO.getPatientById(6).getRisks().get(0));
System.out.println( patient.getRisks().size());
}
Whenever I run this method with a unit test and set rollback to false, it DOES get deleted, but whenever I go there using a controller, it does not actually delete it. I even printed out the size of the list in the DAO method, before the deletion it said 4, afterwards 3, but when I got back in the controller, it somehow went back to 4.
Any help on this is appreciated.
King regards
Judging by the code you posted, you are not working with managed instance of Patient
. Try the same on managed instance, just add patient = em.find(Patient.class, patient.getId())
prior to modifying the patient.
One more thing, remove(risk)
will work properly if equals()
and hashcode()
are implemented in Risk
entity. To be sure, you could make sure it is also managed entity by calling risk = em.find(Risk.class, risk.getId())
.
patient = em.find(Patient.class, patient.getId());
risk = em.find(Risk.class, risk.getId());
patient.getRisks().remove(risk);
return patient;