将MVC数据保存到ORM

时间:2013-07-06 02:15:40

标签: asp.net-mvc hibernate model-view-controller spring-mvc orm

Java或dotNet世界拥有丰富的开源框架和库。我们都喜欢在任何地方使用Spring和Hibernate。 每个人都同意hibernate是一个非常方便的工具。 Hibernate可以做什么?好吧,基本上 - Hibernate可以跟踪我们的域对象更改并仅将修改后的数据保留到数据库,就是这样。 基本上,这就是我们想要的一切。我想从数据库中加载一些记录,对它们进行一些修改,然后调用transaction.commit(),所有修改都会立即保留。 这太棒了,对吧!

但网络世界怎么样?在Web应用程序中,必须关闭数据库会话。 我无法加载某些域对象并等待用户通过HTTP进行修改,并在修改后保留这些对象。

我们必须使用分离的对象或DTO。这个怎么运作 ? 用户在HTML浏览器中进行修改,spring Mvc使用MVC模型绑定自动将这些HTML修改转移到我们的自定义DTO对象, 然后我们做一些编程工作来将修改从DTO对象转移到休眠域对象,然后我们才会坚持它们。 例如 - 我们有一个更新客户地址的Web表单,以及另一个更新客户详细信息的表单。 我们必须有两个不同的业务层方法 - UpdateAddress()和UpdateDetails(),两种方法都必须接受某种DTO, 一个代表地址信息,另一个代表细节信息。 我们还有自定义逻辑,将数据从这两个DTO传输到域类'Customer'。 是的,当然,我们可以重用我们的域类,而不是DTO对象。但它并没有使它更简单。 在这两种情况下,我们仍然必须实现将修改转移到持久对象的自定义逻辑, 我无法立即坚持分离的对象,因为通常域类有很多很多属性代表很多关系,例如。客户有 - 订购物业。当我更新客户地址时,我不想更新其订单。

是否有一种通用的通用方法将修改从mvc模型映射到域对象而无需编写大量自定义代码,并且没有覆盖太多字段的风险?

1 个答案:

答案 0 :(得分:0)

最好有一个数据访问层,转换为每个域对象/实体都有一个存储库。此外,所有存储库共享公共代码,因此您自然拥有一个抽象存储库:

public abstract class AbstractRepository<E extends BaseModel> implements Repository<E> {

    @PersistenceContext
    private EntityManager entityManager;

    private Class<E> entityClass;

    public AbstractRepository(Class<E> entityClass) {
        this.entityClass = entityClass;
    }

    protected EntityManager getEM() {
        return entityManager;
    }

    protected TypedQuery<E> createQuery(String jpql) {
        return createQuery(jpql, entityClass);
    }

    protected <T> TypedQuery<T> createQuery(String jpql, Class<T> typeClass) {
        return getEM().createQuery(jpql, typeClass);
    }

    @Override
    public E merge(E entity) {
        return getEM().merge(entity);
    }

    @Override
    public void remove(E entity) {
        getEM().remove(entity);
    }

    @Override
    public E findById(long id) {
        return getEM().find(entityClass, id);
    }
} 

最好有一个服务层,您可以在其中创建,更新和删除实体的实例(如果您愿意,可以通过DTO将其传递给创建和更新方法)。

...

@Inject
private CustomerRepository customerRepository;

public Customer createCustomer(CustomerDto customerDto) {
    Customer customer = new Customer();
    customer.setEmail(customerDto.getEmail());
    ...
    return customerRepository.merge(customer); 
}

public Customer updateCustomerAddress(Customer customer, String address) {
    customer.setAddress(address);
    return customerRepository.merge(customer);  
}
...

因此,您需要多少更新方法。我通常会将它们分组到常见的操作中,例如更新客户的地址,将客户ID和更新的地址从前端(可能通过ajax)传递给控制器​​,监听特定端点。您可以使用此端点首先通过Id查找实体,然后将其传递给您的服务以进行地址更新。

最后,您需要确保数据实际上是持久化的,因此在Spring中您可以将@Transactional注释添加到Spring MVC控制器或执行持久化的服务。我不知道有关于此的任何最佳做法,但我更喜欢将其添加到我的控制器中,这样无论您使用何种服务,始终保证您都可以进行交易。