Traditionally you would write interfaces that define the contract between your service layer and data layer. You then write implementations and these are your DAOs.
Back to your example. Assuming the relationship between Airport and Airline is many to many with a table containing airport_id and airline_id you might have an interface;
public interface AirportDAO
{
public List getAirlinesOperatingFrom(Set airports);
}
..and you might provide a Hibernate implementation of this;
public class HibernateAirportDAO implements AirportDAO
{
public List getAirlinesOperatingFrom(Set airports)
{
//implementation here using EntityManager.
}
}
You could also look into having a List on your Airline entity and defining the relationship with a @ManyToMany JPA annotation. This would remove the necessity to have this particular DAO method altogether.
You might also want to look into the Abstract Factory pattern for writing DAO factories. For example;
public abstract class DAOFactory
{
private static HibernateDAOFactory hdf = new HibernateDAOFactory();
public abstract AirportDAO getAirlineDAO();
public static DAOFactory getFactory()
{
//return a concrete implementation here, which implementation you
//return might depend on some application configuration settings.
}
}
public class HibernateDAOFactory extends DAOFactory
{
private static EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("myPersistenceUnit");
public static EntityManager getEM()
{
return emFactory.createEntityManager();
}
public AirportDAO getAirportDAO()
{
return new HibernateAirportDAO();
}
}
This pattern allows your HibernateDAOFactory to hold a single EMF and supply individual DAO instances with EMs. If you don't want to go down the fatory route then Spring is great at handling DAO instances for you with dependancy injection.
Edit: Clarified a couple of assumptions.