使用Spring Web MVC解耦后备存储 [英] Decoupling backing store with Spring Web MVC

查看:111
本文介绍了使用Spring Web MVC解耦后备存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个设计模式问题,所以我将通过一个简单的通讯录应用示例来说明它.

This is a design pattern question, so I'll illustrate it with a simple example of an address book app.

首先有一些假设. 1.直接使用DB域对象作为Spring MVC表单的后备存储似乎是可以接受的.

Firstly a few assumptions. 1. It appears to be acceptable to directly use DB domain objects as the backing store for Spring MVC forms.

我的应用程序的迭代1,我创建了一个JPA映射的Person对象,并附加了各种属性.使用DAO模式,我创建了一个持久性对象,该对象可以从数据库中获取所有,存储和删除人员.另外,我有一个工厂方法create,所以我可以得到一个person对象.使用此DAO对象,我创建了一个简单的Web前端.一切都很好.

Iteration 1 of my app I created a JPA mapped Person object with various attributes attached. Using the DAO pattern I created a persistence object which can getAll, store and delete people from the database. In addition I have a factory method, create, so I can get a person object. Using this DAO object I create a simple web front end. All is good.

在迭代2中,我需要支持多种存储类型,因此我为person创建了一个具有多个实现的接口,并为DAO持久性创建了一个接口,并再次具有多个实现.另外,人被扩展为能够具有多个地址.

In iteration 2 I need to support multiple storage types, so I create an interface for person, which has multiple implementations, and an interface for the DAO persistence, again with multiple implementations. Also, person was extended to be able to have multiple addresses.

interface IPerson {
    public String getName();
    public List<IAddress> getAddresses();
}

但是,当涉及到更新Web界面以能够处理这些多种实现时,我遇到了一个问题.持久性实现由Spring注入.而且,由于该持久性对象具有工厂方法,因此我对创建IPerson实现非常有帮助.但是,如果我想做一些事情,例如允许将多个地址作为一个请求的一部分提交,那么我会遇到问题.为了使它与Spring一起使用,您似乎需要使用AutoPopulatingList,因此spring可以仅.get(#)记录副本中的属性.

But, when it comes to updating the web interface to be able to deal with these multiple implementations I have an issue. The persistence implementation is injected by Spring. And, because that persistence object has a factory method I am all good for creating the IPerson implementation. But, if I want to do something fancy like allow multiple addresses be submitted as part of the one request then I have an issue. To allow this to work with Spring you seem to need to use an AutoPopulatingList, so spring can just .get(#) the record an copy the attributes in.

因此,一种可行的解决方案是要求所有持久性实现都使用自动填充列表,并为所有子类创建正确的实现.这样做是否合适,因为我们需要将此@PostLoad与JPA一起应用,因为基本列表已被Hibernate取代.

So, one solution to making this work is to require all persistence implementations use an autopopulating list, and create the correct implementation for all child classes. Is this appropriate, given that we'd need to apply this @PostLoad with JPA as the base lists get replaced by Hibernate.

另一种选择是不对传递给持久性实现的实现进行任何假设,并将对象转换/复制为适当的类型.这样看起来更好,因为然后将Domain对象保持简单,并且所有存储复杂性都在DAO中.在这种情况下,我们将使用IPerson和IAddress接口的Default *实现.

The alternative is to not make any assumptions about the implementation passed into the persistence implementation and convert/copy the objects across to the appropriate type. This looks better, as then the Domain object are kept simple, and all the storage complexity is in the DAO. In this case we'd use a Default* implementation of the IPerson and IAddress interfaces.

尽管我更喜欢第二种选择,但我不一定对这种情况感到满意.谁能提供任何见解或建议?

Even though I like the second option better, I am not necessarily comfortable with this situation. Can anyone offer any insights or advice?

推荐答案

拥有多组包含不同调整的,包含相同业务数据的类真的很讨厌.真是令人讨厌,就像我不得不在抛弃您的一种持久化方式(例如JAXB)和具有多种实现方式之间进行选择一样,我宁愿抛弃该技术并找到一种更好的方式来实现这一点,因为拥有所有那些无意识的代码是一个很大的痛苦.

It is really nasty to have multiple sets of classes that embody the same business data just with different tweakage. Really nasty as in if I had to choose between something like ditching one of your ways of persisting, like JAXB, and having the multiple implentations, I would rather ditch the technology and find a better way to do it, because having all that mindless code is a major pain.

Alan Perlis说:在一个数据结构上运行100个函数比在10个数据结构上运行10个函数要好.您尤其要避免大量重复的数据结构.维护冗余代码库很无聊.

Alan Perlis said, "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." You especially want to avoid data structures that largely duplicate each other. Maintaining a redundant code base is no fun.

我建议您查看域驱动设计.这个想法是您拥有对对象的存储方式一无所知的域对象(这被称为持久性无知").这样,您的域对象可以是POJO,通常不需要在其上放置接口,因为除其他域对象外,它们与应用程序中的任何内容均无关. (可能在某些情况下有用,但不是正常情况.)您可以将业务逻辑(有关域对象如何与其他域对象相关的信息)放入域对象中,而不必担心如何对其进行测试.因为与数据库没有关系.而且,域对象可以在整个应用程序中自由传递,因为它们在特定层上没有任何依赖关系.在依赖关系方面,域层负责应用程序的所有其他部分,但与它们无关.

I suggest you check out Domain-Driven Design. The idea is you have domain objects that do not have any knowledge of how they are stored (this is called Persistence Ignorance). That way your domain objects can be POJOs, you usually don't need to put interfaces on them because they have no dependencies on anything in your application except for other domain objects. (There might be edge cases where it becomes useful but it would not be the normal case.) You can put your business logic (information about how your domain object relates to other domain objects) in the domain object without worrying about how to test it because there's no tie to the database. Also the domain objects can be passed around freely throughout your application because they don't have any dependencies on a specific layer. In terms of dependencies the domain layer is responsible to all the other parts of the app, but independent of them.

所有这一切的结果是,域逻辑和对象存储方式的技术细节成为单独的关注点,因此可以分别进行测试.此外,您还具有一个中央数据结构,该数据结构将所有业务数据仅存储在一个位置,因此在发生更改时无需进行多个更改.

The upshot of all this is that domain logic and technical details of how objects are stored become separate concerns so each can be tested separately. Also you have a central data structure that holds all the business data in only one place so you don't have multiple changes to make when something changes.

有关域驱动设计的免费书籍,可从 http://www.infoq.com .

There is a free web book available on Domain-Driven Design from http://www.infoq.com.

这篇关于使用Spring Web MVC解耦后备存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆