简体   繁体   中英

spring mvc module not updating record

In a spring mvc application that uses hibernate an jpa, I have a module for editing phone numbers which is not committing changes to the database when the user enters altered information for phone number and phone number type. I keep going over the code, but I cannot see where the problem is. Can someone show me what to change in the below?

Here are the relevant methods of PhoneNumberController.java:

@RequestMapping(value = "/patients/{patientId}/phonenumbers/{phonenumberId}/edit", method = RequestMethod.GET)
public String initUpdateForm(@PathVariable("phonenumberId") int phonenumberId, Map<String, Object> model) {
    System.out.println("--------------------------------- made it into initUpdateForm() method");
    PhoneNumber phonenumber = this.clinicService.findPhoneNumberById(phonenumberId);
    model.put("phonenumber", phonenumber);
    return "phonenumbers/createOrUpdatePhoneNumberForm";
}

@RequestMapping(value = "/patients/{patientId}/phonenumbers/{phonenumberId}/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public String processUpdateForm(@ModelAttribute("phonenumber") PhoneNumber phonenumber, BindingResult result, SessionStatus status) {
    // we're not using @Valid annotation here because it is easier to define such validation rule in Java
    new PhoneNumberValidator().validate(phonenumber, result);
    if (result.hasErrors()) {return "phonenumbers/createOrUpdatePhoneNumberForm";}
    else {
        this.clinicService.savePhoneNumber(phonenumber);
        status.setComplete();
        return "redirect:/patients?patientID={patientId}&type=phone";
    }
}

Here is the PhoneNumber.java model:

@Entity
@Table(name = "patient_phone_numbers")
public class PhoneNumber {
@Id
@GeneratedValue
@Column(name="id")
private Integer id;

@ManyToOne
@JoinColumn(name = "client_id")
private Patient patient;

@Column(name="phonenumber")
private String number;

@ManyToOne
@JoinColumn(name = "type_id")
private PhoneNumberType type;

@Column(name = "preferred")
private boolean preferred;

@Column(name = "okmessages")
private boolean okmessages;

public Integer getId(){return id;}
public void setId(Integer i){id=i;}

protected void setPatient(Patient patient) {this.patient = patient;}
public Patient getPatient(){return this.patient;}

public String getNumber(){return number;}
public void setNumber(String pn){number=pn;}

public PhoneNumberType getType(){return this.type;}
public void setType(PhoneNumberType nt){this.type=nt;}

public boolean getPreferred(){return preferred;}
public void setPreferred(boolean p){preferred=p;}

public boolean getOkmessages(){return okmessages;}
public void setOkmessages(boolean m){okmessages=m;}

public boolean isNew() {return (this.id == null);}
}

And here is the createOrUpdatePhoneNumberForm.jsp:

<html lang="en">
<jsp:include page="../fragments/headTag.jsp"/>
<body>
<div class="container">
<jsp:include page="../fragments/bodyHeader.jsp"/>
<c:choose>
    <c:when test="${phonenumber['new']}">
        <c:set var="method" value="post"/>
    </c:when>
    <c:otherwise>
        <c:set var="method" value="put"/>
    </c:otherwise>
</c:choose>

<h2>
    <c:if test="${phonenumber['new']}">New </c:if>
    Phone Number
</h2>

<form:form modelAttribute="phonenumber" method="${method}" class="form-horizontal">
    <div class="control-group" id="patient">
        <label class="control-label">Patient </label>
        <c:out value="${phonenumber.patient.firstName} ${phonenumber.patient.lastName}"/>
    </div>

    <petclinic:inputField label="PhoneNumber" name="number"/>
    <div class="control-group">
        <petclinic:selectField name="type" label="Type" names="${numtypes}" size="5"/>
    </div>
    Preferred number? <form:checkbox path="preferred"/><br>
    OK to leave messages? <form:checkbox path="okmessages"/>
    <td>
    </td>

    <div class="form-actions">
        <c:choose>
            <c:when test="${phonenumber['new']}">
                <button type="submit">Add Phone Number</button>
            </c:when>
            <c:otherwise>
                <button type="submit">Update Phone Number</button> <h3>    Link to delete will go here.</h3>
            </c:otherwise>
        </c:choose>
    </div>
</form:form>
<c:if test="${!phonenumber['new']}">
</c:if>
</div>
</body>
</html>

ClinicService.java is:

@Service
public class ClinicServiceImpl implements ClinicService {

private DocumentRepository documentRepository;
private PatientRepository patientRepository;
private AddressRepository addressRepository;
private PhoneNumberRepository phoneNumberRepository;

@Autowired
public ClinicServiceImpl(DocumentRepository documentRepository, PatientRepository patientRepository, AddressRepository addressRepository, PhoneNumberRepository phoneNumberRepository) {
    this.documentRepository = documentRepository;
    this.patientRepository = patientRepository;
    this.addressRepository = addressRepository;
    this.phoneNumberRepository = phoneNumberRepository;
}

@Override
@Transactional(readOnly = true)
public Collection<DocumentType> findDocumentTypes() throws DataAccessException {return documentRepository.findDocumentTypes();}

@Override
@Transactional(readOnly = true)
public Collection<Gender> findGenders() throws DataAccessException {return patientRepository.findGenders();}

@Override
@Transactional(readOnly = true)
public Collection<Race> findRaces() throws DataAccessException {return patientRepository.findRaces();}

@Override
@Transactional(readOnly = true)
public Patient findPatientById(int id) throws DataAccessException {return patientRepository.findById(id);}

@Override
@Transactional(readOnly = true)
public Collection<Patient> findPatientByLastName(String lastName) throws DataAccessException {return patientRepository.findByLastName(lastName);}

@Override
@Transactional
public void savePatient(Patient patient) throws DataAccessException {
    System.out.println("-------------------------------------- inside clinicservice.savePatient()");
    patientRepository.save(patient);}

@Override
@Transactional(readOnly = true)
public Document findDocumentById(int id) throws DataAccessException {
    System.out.println("--------------- made it into clinicservice.findDocumentById() method");
    return documentRepository.findById(id);}

@Override
@Transactional
public void saveDocument(Document doc) throws DataAccessException {documentRepository.save(doc);}

@Override
@Transactional
public void saveAddress(Address addr) throws DataAccessException {addressRepository.save(addr);}

@Override
@Transactional(readOnly=true)
public Address findAddressById(int id) throws DataAccessException {return addressRepository.findById(id);}

@Override
@Transactional(readOnly = true)
public Collection<State> findStates() throws DataAccessException {return addressRepository.findStates();}

@Override
@Transactional(readOnly = true)
public Collection<PhoneNumberType> findPhoneNumberTypes() throws DataAccessException {return phoneNumberRepository.findPhoneNumberTypes();}

@Override
@Transactional(readOnly = true)
public void savePhoneNumber(PhoneNumber pn) throws DataAccessException {
    System.out.println("++++++++++++++++++++ inside savePhoneNumber(pn) : "+pn.getNumber()+" , "+pn.getType().getName());
    phoneNumberRepository.save(pn);
}

@Override
@Transactional(readOnly=true)
public PhoneNumber findPhoneNumberById(int id) throws DataAccessException {return phoneNumberRepository.findById(id);}
}

JpaPhoneNumberRepository.java contains the following:

@PersistenceContext
private EntityManager em;

@Override
public void save(PhoneNumber phonenumber) {
    System.out.println("------------------------------ inside save(phonenumber) : "+phonenumber.getNumber()+" , "+phonenumber.getType().getName());
    if (phonenumber.getId() == null) {
        System.out.println("phonenumber.getId() == null ");
        this.em.persist(phonenumber);
    }
    else {
        System.out.println("else");
        this.em.merge(phonenumber);}
}

The correct new values for getNumber() and getType().getName() print out. And "else" prints out, but then the data is not updated in the database. Why not? (note that clinicservice calls this save() method of JpaPhoneNumberRepository.java .)

The problem is that you have ClinicServiceImpl > savePhoneNumber method annotated as @Transactional(readOnly = true) . Change it to @Transactional

Why is the savePhoneNumber method in your ClinicService.java as @Transactional(readOnly=True) ? That is the cause of the problem

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