开发者

Are there patterns for model / entity classes

What is the best approach to take when you are pulling model objects from multiple datasources?

For example I have an application has has some data stored in a mySQL database using hibernate. What If I wanted to store some other objects in EC2 or Google App Engine? I understand that DAO's abstract the implementation of working with a particular data source, but what about the entities themselves?

At first I thought annotating my entities with jpa annotations was a great solution, but now it seems like i've really tied my entities down to a particular implementation. In the case of App Engine for example, some of these annotations make no sense.

It seems like i need a pure POJO class to represent my entities, entirely free of persistence logic. If I wanted to model a Dog for example (yes lame choice, but whatever).

Would it make sense to have an abstract Dog class, t开发者_高级运维hen define subclasses to work with particular persistence solutions: HibernateDog, GAEDog, etc.

Thanks.


This is a great question, even if the issue isn't new. As an industry, we've been changing the "conventional wisdom" on this subject frequently over the years. The answers you get today aren't necessarily what you'd get 5 years ago or 5 years in the future.

In picturing how I'd like to handle this item, I'm wondering about some things you haven't stated: is your app the "system of record" for Dog entities? What other subsystems/layers/apps need to know about Dog entities.

In Java, when you write brand new types like Animal > Dog, you get the following reward: the opportunity to write a whole bunch more code that knows how to interact with Animal objects and Dog objects. I'm less convinced in 2010 that this is a good idea than I was five years ago.

Are you responsible for designing the database where Dog information is stored? We used to do that all the time, but nowadays I usually find myself integrating with data records that are actually managed by other systems: google APIs, LDAP entities, data warehouses, products like peoplesoft, etc.

If you're not in charge of defining what a Dog is and how they interact with the universe, I'd look at a domain-agnostic way to model Dog information in memory. There are tons: XML/DOM, JSON, Map, etc.

The advantages of moving other people's data around in these formats are many...

  • you don't have to write POJOs
  • these are rich in features, documentation, and testing
  • there are numerous existing APIs to transform, manipulate, and serialize these creatures
  • you might get to reuse your view/controller/other code across other domains

On the other hand... if you are the system of record for Dog data, consider using interfaces instead of abstract classes. Or perhaps interfaces and abstract classes. Java only has single inheritance; tie your view/controller/other code to interfaces to guarentee the most future flexibility.


One of the problems with Hibernate is that it injects its own Collection implementations into your domain class, causing problems if you try to send your class over the wire using serialization (e.g. from server to client).

In your above example I would question the need to provide storage-specific sub-classes:

Do / Should the classes really contain state pertaining to the way in which they were stored? i.e. Is this a concept central to the class and hence worthy of using up your "one shot" at inheritance (in Java that is)? I would argue that a more useful inheritance hierarchy in your example would be something like:

  • Animal
    • Mammal
      • Dog
      • Cat

In addition, with the design you propose you might run into problems if, for example you wish to save a Dog instance to Hibernate but don't know whether the Dog is a HibernateDog, GAEDog, etc and have to perform checks / downcasting at this point.


JPA annotations can be nice in that they allow you to place your object-relational mapping (ORM) metadata in the same files as your entity classes, but you are absolutely right that there is a mixing of concerns when you combine JPA metadata with "pure" POJOs. It's a trade-off.

There is an alternative, however. You can externalize the ORM configuration in XML files and in that way keep those details out of your entity classes. JPA provides an XML configuration syntax, but for my projects, I prefer to use native Hibernate XML mappings for the added flexibility they provide. It may not be as fashionable as an annotation-based approach, but in my experience, it works quite well.


You are right in using a DAO layer to abstract the datasource details from other layers. Thus the model layer should actually have no knowledge of which data storing technique or which database is being used.

The answer to your question will be: Use Service layer. This is the layer where you put all your business code. Which entity to instantiate, which DAO to use, how to corroborate data, transaction demarcation etc

So, the service layer should be incharge of loading/persisting your entities. And that's where you should embed the logic about what datasource/database to use. Use Spring's dependency injection to help you with that. Inject your choice of the DAOs,Entities into the Service layer.

Entity classes: Dog, Cat

Service classes: AnimalCenterService

DAO classes: AnimalCenterHibernate, AnimalCenterJDBC

Let me know if more explanation is needed. Just my 2 cents


What you have seems to be the correct way. Good design doesn't mean that entities aren't tied to a technology, it just means that if you change the technology you only change 1 layer of your app.

Entities with JPA are a good solution if you're using JPA. Besides those entities you can have more "entities" (POJOs) that are connected to GAE, etc.

About the abstract dog and subclasses, that seems an overkill, except if you really, really need to. If you really need to, please check DTO objects: http://en.wikipedia.org/wiki/Data_transfer_object

DTOs are used to transfer the object to upper layers (above DAO) in a consistent way (and make it serializable) even when dealing with multiple datasources/technologies in the persistence layer.


You will not want to have your persistence specific code inherit from your entity classes since that would make it impossible to use inheritance for your domain entity classes. For example if you have HibernateDog inherit from Dog then you won't be allowed to have Poodle inherit from Dog without forcing Poodle to be Hibernate specific.

One approach that works is to use Data Entities that are persistence specific. Your domain entity classes would delegate to the data entity object for its persistent attributes via an interface. You could then substitute different persistence implementation specific data entity classes as long as they conform to your data entity interface.

Dog references (and delegates to) DogEntity interface. Poodle inherits from Dog, PoodleEntity inherits from DogEntity.

HibernateDog implements DogEntity
HibernatePoodle implements PoodleEntity and inherits from HibernateDog.
...
StubDog implements DogEntity
StubPoodle implements PoodleEntity and inherits from StubDog
...

You could have as many data entity types as you want. The Data Entities would be very thin and would only hold the persistent member variables and the annotations or whatever other code is necessary for persistence.

The Domain Entities would contain the entity specific business logic.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜