JPA: one DAO for all the entities or one for each entity?

dao, eclipselink, entity, java, jpa

Solution

It looks like you try to invent Generic DAO pattern. If so, you're essentially on the right way.

Generic DAO pattern works as follows:

Create a generic base class that all your DAOs will extend:

public abstract class GenericDao<E, ID extends Serializable> {
    ...
    // Implement common operations that are relevant to all entities here:
    public E findById(ID id) { ... }
    public void save(E entity) { ... }
    // etc
    ...
}

Create concrete DAO implementations by extending `GenericDao`:

public class EntityEmailDao extends GenericDao<EntityEmail, Integer> {
    // This class may contain operations that are relevant to specific entity:
    public E findByEmail(String email) { ... }
}

Since `GenericDao` is generic, you don't need to make your entities extend any common interface

There are plenty of exisiting implementations of this pattern around, take a look, for example, here.

Problem

First of all, sorry for my english. Im making, for a friend, a desktop application with JPA(EclipseLink) that access a SQLite database. I already created the database and the entities in Eclipse. But i also created a class called `UniversalDAO` which is an utility class used by all the entities to access and persist the database: ``` package model.DAO; import java.util.ArrayList; import javax.persistence.*; import model.entities.Entities; public class UniversalDAO { private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("TheDatabase"); private static EntityManager em = emf.createEntityManager(); private UniversalDAO (){} public static void close(){ em.close(); emf.close(); } public static Entities getOne(Class<? extends Entities> table, Object primaryKey) { return em.find(table, primaryKey); } public static ArrayList<Entities> getAll(Class<? extends Entities> table) { ArrayList<Entities> ret = new ArrayList<>(); for(Object obj : em.createQuery("SELECT o FROM " + table.getName() + " o").getResultList()) ret.add((Entities) obj); return ret; } public static ArrayList<Entities> getWithCondition(Class<? extends Entities> table, String condition) { ArrayList<Entities> ret = new ArrayList<>(); for(Object obj : em.createQuery("SELECT o FROM " + table.getName() + " o WHERE " + condition).getResultList()) ret.add((Entities) obj); return ret; } public static void insert(Entities row) { em.getTransaction().begin(); em.persist(row); em.flush(); em.getTransaction().commit(); } public static void update(Entities row) { em.getTransaction().begin(); em.merge(row); em.flush(); em.getTransaction().commit(); } public static void delete(Class<? extends Entities> table, Object primaryKey) { em.getTransaction().begin(); Entities row = em.find(table, primaryKey); em.remove(row); em.flush(); em.getTransaction().commit(); } } ``` To group all the entites and use them in this class i created an empty interface called `Entities`. This is how one of the entities looks like: ``` package model.entities; import java.util.ArrayList; import javax.persistence.*; @Entity @Table(name="emails") public class EntityEmail implements Entities { @Id @Column(name="id_email") @GeneratedValue(strategy=GenerationType.SEQUENCE) private int idEmail; @Column(name="email") private String email; @Column(name="description") private String description; @ManyToMany(fetch=FetchType.EAGER) @JoinTable(name="people_emails", joinColumns=@JoinColumn(name="id_email", referencedColumnName="id_email"), inverseJoinColumns=@JoinColumn(name="id_person", referencedColumnName="id_person")) private ArrayList<EntityPerson> people; public EntityEmail() { } public int getIdEmail() { return this.idEmail; } public void setIdEmail(int idEmail) { this.idEmail = idEmail; } public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public ArrayList<EntityPerson> getPeople() { return people; } public void setPeople(ArrayList<EntityPerson> people) { this.people = people; } } ``` Like you can appreciate im not a professional and i still have a lot to learn. So, i was wondering if this approach is correct or if i should have one DAO for each entity.

Original source