You can use the repository template. Put your business logic in the service and insert the repository (which abstracts the save mechanism) and the manager into it. The repository hides persistence implementation details from the business service, and entities are simply POJOs.
It will look something like this: Foo is the identifier of the object bar:
public class CarService { @Inject CarRepository carRepository; @Inject CarManager manager; piblic void operate(final Foo foo) { Bar myBar = carRepository.retrieve(foo); manager.doSomethingTo(myBar); carRepository.persist(myBar); } }
See also: Repository Template Step by Step Explanation , http://deviq.com/repository-pattern/ , Some frameworks, such as Spring Data JPA or deltaspike, already implement the repository template for you, all you have to do is provide an interface similar to the following and they generate an implementation in the background:
@Repository public interface CarRepository extends EntityRepository<Car, UUID> {}
Mark in response to your request in more detail. I am going to provide a reconstructed solution, because the example in the question really does not make sense to me and demonstrates quite a few anti-patterns that lead to problematic software.
To find a good solution to the problem, it touches on many different considerations, many of which are very large topics with many books written about them, but I will try my best to illustrate my thinking on their basis in order to solve the above problem.
And apologize because I have no doubt that you know about many of them, but I will assume limited knowledge for the sake of clarity.
The first step in solving this problem is not the code, but the model itself, development based on the model is widely covered in the book of Eric Evan, as indicated in the comments below. The model should lead the implementation, and also should exist at its level as part of a multi-level architecture and consists of objects, value objects and factories.
Developed Development Model
In the model asked in the question, we have something called a state that contains AbstractPlanes and AbstractCars. You use JPA to maintain a state that is actually the aggregate of your planes and cars. Firstly, to call any of the conditions in the software is a bad smell, because almost everything has some kind of condition, but by calling what we have here, which is the totality, the state makes even less sense.
How is one state different from another? Is one car part of one state and another part of another state, or is it so that all aircraft and cars belong to one state. What is the relationship between airplanes and cars in this scenario? How does the list of planes and the list of cars have anything to do with one state?
Well, if the state was actually an Airport, and we were interested in how many planes and cars were currently on the ground, then this might be the right model. If the state were an airport, it would have a name or identifier, such as an airport code, but that is not so ...
... In this case, it seems that State is an object that is used for ease of access to the object model. Thus, we effectively manage our model with implementation considerations, when we must do it the other way around and manage our implementation with our model.
Terms such as CarData are also problematic for the same reason, creating a Car object, and then a separate object to store its data is messy and confusing.
Failure to get the right model leads to software that is confusing at best and, at worst, completely dysfunctional. This is one of the biggest causes of failed IT programs, and the larger the project, the more difficult it is to do it.
Revised Model
So, from the model, I understand that we have Cars, and we have Planes, instances of which are all unique entities with their own identity. It seems to me that they are separate things, and therefore it makes no sense to transfer them into some kind of aggregate entity.
public class Plane {...} public class Car {...}
Another consideration is the use of abstract classes in the model, as a rule, we want to apply the principle to support composition over inheritance , since inheritance can lead to hidden behavior and can make the model difficult to read. For example, why do we have ProperllerPlane and EnginePlane? Of course, is a propeller just a type of engine? I greatly simplified the model:
public class Plane implements Serializable { @Id private String name; private String model; private List<Engine> engines;
An airplane is an entity with its attributes and identification. There is no need to have additional classes that do not represent anything in the real world for storing attributes. Currently, the engine object is an enumeration representing the type of engine used in the plane:
public enum Engine { PROPELLER, JET }
If the engine itself required identification, since in real life cycles engine serial numbers and things are tracked, we will change this to an object. But we do not want to allow access to it, except through an instance of the Plane entity, in which case Plane will be known as the aggregate root - this is an extended topic, and I would recommend Evan's book for more information on aggregates.
The same applies to the Car object.
@Entity public class Car implements Serializable{ @Id private String registration; private String type; private int year;
The above is all that you need, from what was provided in the question, for the foundation of your model. Then I created a couple of factory classes that handle instantiating these objects:
public class CarFactory { public Car makePosrche(final String registrationNumber) { Car porsche = new Car(); porsche.setRegistration(registrationNumber); porsche.setType("Posrshe"); porsche.setYear(1986); return porsche; } } public class PlaneFactory { public Plane makeSevenFourSeven(final String name) { Plane sevenFourSeven = new Plane(); List<Engine> engines = new ArrayList<Engine>(); engines.add(JET); engines.add(JET); engines.add(JET); engines.add(JET); sevenFourSeven.setEngines(engines); sevenFourSeven.setName(name); return sevenFourSeven; } public Plane makeSpitFire(final String name) { Plane spitFire = new Plane(); List<Engine> engines = new ArrayList<Engine>(); engines.add(PROPELLER); spitFire.setEngines(engines); spitFire.setModel("Spitfire"); spitFire.setName(name); return spitFire; } }
What we are doing here is a separation of problems, because in accordance with the principle of shared responsibility, each class should really do only one thing.
Now that we have a model, we need to know how to interact with it. In this case, we will most likely use JPA for cars in a table called Car and Planes. We would provide access to these persistent objects through repositories, CarRepository and PlaneRespository.
Then you can create classes called services that introduce repositories (and all you need) to perform CRUD (Create Read Update Delete) operations on instances of cars and aircraft, and this is also the moment when you can apply your business environment logic to these. For example, your method:
void operate(int i) {..}
By structuring your code in this way, you separate the model (objects and value objects) from how they are stored (stores) from the services that work with them, as indicated in your question:
I am looking for a design that separates the injection from the data storage process.