JPA, inheritance and instance

I use JPA inheritance using the JOIN strategy (JPA2 / Hibernate). I have an abstract general Event object with common fields (date, time, place, etc.) And its children, let's say OutdoorEvent, ClassicalMusicEvent, etc. With specific fields for each type. I do a search on all events, getting the List<Event> that I am showing. The handling for each type of event is different, so I need to find out the type of event for each Event object. Now here is the problem. I came up with two solutions. First, the instanceof keyword:

 if (event instanceof OutdoorEvent) { ... } else if (event instanceof OtherKindOfEvent) { ... } etc. 

Secondly, I add a transitional enumeration field to the Event entity and set this field in each child type constructor. Then I could do:

 if (event.getType() == EventType.OutdoorEvent) { ... } else if (event.getType() == EventType.OtherKindOfEvent) { ... } etc. 

Which solution is better or more OOP? Is there any other solution for this?

+4
source share
4 answers

This is a good question, because the use of polymorphism would be the best solution for OOP. On your abstract event class, add the abstract method "process", and then do the required processing in your subclasses. Then you can just call process() and don't care what type of subclass it has.

However, you probably want your events (i.e. data) to be separate from the logic, so somewhere you are probably going to do instanceof or something like your enum.

I have no preference, it is possible that one is faster than the other, and I will probably go with an enumeration, and not with an instance for speed (he wants to hear if someone knows about it).

If you go with the listing In your event example, you should use a switch instead of if..else.

+4
source

If you are dealing with Hibernate, then you should prepare for cases with Hibernate Proxies (see, for example, Running Hibernate firmware for subclasses ): in your example, the variable event can be a dynamically created instance of HibernateProxy, and the event instanceof OtherKindOfEvent does not work in this case will be.

Thus, you will need a de-proxy (using the Hibernate utilities and loss of JPA abstraction) or use the approach as you mentioned. Therefore, my personal preference is the second option (or something similar to it).

+2
source

The most OOP approach is to use a visitor template.

Put the display processing logic in the visitor:

 public VisitorImpl implements Visitor { public void handleOutdoorEvent(OutdoorEvent event) { .. } public void handleOtherKindOfEvent(OtherKindOfEvent event) { .. } } 

And then on each subclass there is:

 public void handleDisplay(Visitor visitor) { visitor.visit(this); } 

Then, instead of the few checks you just did:

 Visitor visitor = new VisitorImpl(..); for (..) { entity.visit(visitor); } 

In addition, instanceof looks cleaner.

+2
source

Simple strategy:

 Map<Class<?>,Handler> handlers = new ArrayList(); handlers.add(SomeClass1.class, new Handler1()); handlers.add(SomeClass2.class, new Handler2()); handlers.add(SomeClass3.class, new Handler3()); .... for(Entity e : entities){ handlers.get(e.getClass()).execute(e); } 
0
source

All Articles