Мы используем объектные компоненты JPA в качестве нашей модели для контроллера Spring MVC на странице jsp.Одна из наших страниц JSP является частичным представлением этой сущности, которая не показывает все свойства.Всякий раз, когда мы пытаемся обновить нашу сущность, используя сервисный уровень из контроллера, сохраняются только свойства, используемые в форме jsp, а все остальные обнуляются.Как правильно справиться с этой ситуацией?Мы не хотим указывать скрытые поля в форме.
Так что в этом случае, когда контроллер вызывает метод service.update (client), поле имени будет нулевым, поскольку оно не существует в форме.jsp.
form.jsp
<form:form modelAttribute="client" method="get" action="${action}">
<table width="100%">
<tr>
<td>
<table>
<tr>
<td valign="top"><spring:message code="label.tradeOrderManagementSystem"/>:</td>
<td>
<form:select path="tradeOrderManagementSystems" >
<form:options items="${tradeOrderManagementSystemList}" itemValue="id" itemLabel="name" />
</form:select>
<a href="<spring:url value="/tradeOrderManagementSystem/add"/>" class="addAndReturn"><span><spring:message code="add"/></span></a>
</td>
<td>
<form:errors path="tradeOrderManagementSystems" cssClass="errors" />
</td>
</tr>
<tr><td></td><td> </td></tr>
</table>
</td>
</tr>
</table>
<input type="hidden" name="submitted" value="true">
контроллер
@RequestMapping("/{id}/edit")
public ModelAndView edit(HttpServletRequest request,
HttpServletResponse response,
@ModelAttribute("client") Client client,
BindingResult result,
@PathVariable("id") int id,
Model model) {
ControllerContext ctx = new ControllerContext(request, response);
init(ctx);
setAdvancedSearchAvailable(ctx, true);
buildShowAndEditVerticalMenu(ctx, id, false);
if (id == 0) {
result.addError(new ObjectError("client", getMessage("error.idNeeded")));
return getModelAndView(ctx, "itEfficiencies/form");
} else {
if (!isSubmission(ctx)) {
client = clientService.find(id);
model.addAttribute("client", client);
fillClientForm(model);
return getModelAndView(ctx, "itEfficiencies/form");
} else {
//clientValidator.validate(client, result);
if (result.hasErrors()) {
fillClientForm(model);
return getModelAndView(ctx, "itEfficiencies/form");
} else {
try {
//checkClientProperties(client);
client.setId(id);
client = clientService.update(client); //method updates only form fields and nulls out all others
} catch (Exception e) {
e.printStackTrace();
result.addError(new ObjectError("client", getMessage("error.save")));
fillClientForm(model);
return getModelAndView(ctx, "itEfficiencies/form");
}
return getModelAndView(ctx, "/staffingByClient/" + client.getId() + "/show", true);
}
}
}
}
Client.java
@Entity
public class Client extends AbstractEntity<Integer> {
private static final long serialVersionUID = 1L;
public static final String FIND_BY_NAME = "Client.FIND_BY_NAME";
public static final String COUNT_BY_NAME = "Client.COUNT_BY_NAME";
@Basic(optional = false)
@Column(nullable = false, length = 125)
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(inverseJoinColumns = {
@JoinColumn(name = "trade_order_management_system_id")}, uniqueConstraints =
@UniqueConstraint(name = "UK_client_trade_order_mgmt_client_id_trade_order_mgmt_id",
columnNames = {"client_id", "trade_order_management_system_id"}))
@ForeignKey(name = "FK_client_trade_order_management_systems_client_id",
inverseName = "FK_client_trade_order_mgmt_sys_trade_order_management_system_id")
private List<TradeOrderManagementSystem> tradeOrderManagementSystems;
public Client() {
}
public Client(Integer id) {
this.id = id;
}
public Client(Integer id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<TradeOrderManagementSystem> getTradeOrderManagementSystems() {
return tradeOrderManagementSystems;
}
public void setTradeOrderManagementSystems(List<TradeOrderManagementSystem> tradeOrderManagementSystems) {
this.tradeOrderManagementSystems = tradeOrderManagementSystems;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Client)) {
return false;
}
Client other = (Client) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
}
методы обслуживания
public abstract class CrudService<T, ID extends Serializable> extends DAOImpl<T, ID> {
/**
* Updates an entity from an existing entity.
*
* @since 0.0.1
*
* @param entity
* @return the managed instance of the updated entity
*/
@Override
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public T update(T entity, ID id) {
return super.update(assignDefaultValues(entity), id);
}
}
public abstract class DAOImpl<T, ID extends Serializable> implements DAO<T, ID> {
private Class<T> persistentClass;
@PersistenceContext(unitName = "krfsPersistenceUnit")
protected EntityManager entityManager;
/**
* Instantiates an instance of this class and sets the <code>persistentClass</code>
* based on the identifier type
*
* @since 0.0.1
*/
public DAOImpl() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
/**
* @since 0.0.1
*
* @return the type to be persisted
*/
@Override
public Class<T> getPersistentClass() {
return persistentClass;
}
/**
* Updates an entity from an existing entity.
*
* @since 0.0.1
*
* @param entity
* @param id the identifier of the entity
*
* @return the managed instance of the updated entity
*/
@Override
public T update(T entity, ID id) {
//Find a managed instance of the entity first and copy the properties
//to the passed in entity before merging. This ensures that entityManager
//will not create a new entity with merge.
Object ref = this.entityManager.getReference(persistentClass, id);
if (ref != null) {
BeanUtils.copyProperties(entity, ref);
}
return (T) this.entityManager.merge(ref);
}
}