代码之家  ›  专栏  ›  技术社区  ›  dukethrash

如何从JSP页面保存JPA实体模型属性的特定属性

  •  1
  • dukethrash  · 技术社区  · 15 年前

    我们在jsp页面上使用JPA实体bean作为springmvc控制器的模型。我们的一个jsp页面是这个实体的局部视图,它没有显示所有属性。每当我们尝试从控制器使用服务层更新实体时,只有jsp表单上使用的属性被持久化,其他所有属性都被清空。处理这种情况的正确方法是什么?我们不希望必须在窗体上指定隐藏字段。

    所以在这种情况下,当控制器调用服务.更新(client)方法名称字段将为空,因为在表单.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>&nbsp;</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);
                }
            }
        }
    }    
    

    @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);
    }
    

    }

    1 回复  |  直到 15 年前
        1
  •  1
  •   Pascal Thivent    15 年前

    您没有提供足够的细节(特别是,显示如何保存表单中的值的代码会有所帮助),但我怀疑您正在将分离的实体与 null merge 工作(它将分离实体的状态复制到持久性上下文中加载的具有相同数据库标识符的实体上),得到空值。

    • 以某种方式保留分离的实体,将表单中的值复制到其中,然后 是~还是~

    如果我漏掉了重点,请提供更多的细节来理解这个问题。

    更新: 我不懂你的密码。你在复制属性 ref entity (从视图中分离的客户端),然后合并 ... 不,我不明白。

    推荐文章