The DAO must provide access to one related data source and, depending on how complex your business model is, will return either full-fledged business objects or simple data objects. In any case, DAO methods should reflect the database somewhat closely.
A service can provide a higher-level interface that not only processes your business objects, but also allows you to access them in the first place. If I get a business object from the Service, this object can be created from different databases (and different DAOs), it can be decorated with information made from an HTTP request. It can have a specific business logic that converts multiple data objects into a single, reliable business object.
I generally create a DAO, thinking that it will be used by anyone who is going to use this database or a set of data related to the business, this is literally the lowest level of code, except for triggers, functions and stored procedures in the database.
Answers to specific questions:
I was wondering if the DAOs can contain methods that actually don't have much to do with data access, but is the easiest way to execute the query?
in most cases not, you will need your more complex business logic at the service level, collecting data from individual requests. However, if you are concerned about processing speed, the service level can delegate the DAO action, even if it violates the beauty of the model, much like a C ++ programmer can write assembler code to speed up certain actions.
It seems to me that I am more of a service level method, but I am not sure if using the JPA EntityManager in the service level is an example of good practice?
If you intend to use the entity manager in your service, then think of the entity manager as your DAO, because that is exactly what it is. If you need to remove redundant query building, do not do this in your service class, retrieve it in the class that uses the entity manager, and do it DAO. If your use case is really simple, you can completely skip the service level and use the entity manager or DAO in the controllers, because all your services will transfer calls to getAirplaneById() in the DAO findAirplaneById()
UPDATE. To clarify the discussion below, using an entity manager in a service is probably not the best solution in most situations, where there is also a DAO level for various reasons highlighted in the comments. But, in my opinion, this would be quite reasonable:
- The service must interact with different data sets.
- At least one dataset already has a DAO
- The service class is in a module that requires some persistence, which is simple enough to not guarantee its own DAO
Example.
//some system that contains all our customers information class PersonDao { findPersonBySSN( long ssn ) } //some other system where we store pets class PetDao { findPetsByAreaCode() findCatByFullName() } //some web portal your building has this service class OurPortalPetLostAndFoundService { notifyOfLocalLostPets( Person p ) { Location l = ourPortalEntityManager.findSingle( PortalUser.class, p.getSSN() ) .getOptions().getLocation(); ... use other DAO to get contact information and pets... } }