【发布时间】:2013-12-31 00:37:26
【问题描述】:
在使用 hibernate an jpa 的 spring mvc 应用程序中,我有一个用于编辑电话号码的模块,当用户输入电话号码和电话号码类型的更改信息时,该模块不会对数据库进行更改。我继续检查代码,但我看不出问题出在哪里。有人可以告诉我在下面要改变什么吗?
这里是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";
}
}
这里是 PhoneNumber.java 模型:
@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);}
}
这里是 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 是:
@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 包含以下内容:
@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);}
}
打印出getNumber() 和getType().getName() 的正确新值。并且"else" 打印出来,但是数据库中的数据没有更新。为什么不? (请注意,clinicservice 调用 JpaPhoneNumberRepository.java 的 save() 方法。)
【问题讨论】:
-
您在保存之前是否在
processUpdateForm中输入了System.out,以确保应用表单中的更改?您可以在那里消除一半的搜索。 -
那么
clinicService是什么? Spring JPA 存储库?您自己实现了任何方法吗? -
@chrylis ClinicService 代码可以在以下链接中看到,尽管我已经对其进行了一些编辑以使用电话号码等:github.com/spring-projects/spring-petclinic/tree/master/src/…
-
请发布您自己的代码。整个问题在于您对 Pet Clinic 应用程序的修改,尤其是您的
savePhoneNumber方法。 -
@chrylis 我刚刚从 JpaPhoneNumberRepository.java 添加了相关方法,该方法在应该更新实体管理器中数据的代码之前打印出正确更新的值。为了找到问题,您还需要什么?
标签: java spring hibernate spring-mvc jpa