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模型映射到域对象而无需编写大量自定义代码,并且没有覆盖太多字段的风险?
答案 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控制器或执行持久化的服务。我不知道有关于此的任何最佳做法,但我更喜欢将其添加到我的控制器中,这样无论您使用何种服务,始终保证您都可以进行交易。