JPA:所有实体一个 DAO,还是每个实体一个 DAO?
Posted
技术标签:
【中文标题】JPA:所有实体一个 DAO,还是每个实体一个 DAO?【英文标题】:JPA: one DAO for all the entities or one for each entity? 【发布时间】:2014-09-02 03:02:52 【问题描述】:首先,对不起我的英语。
我正在为朋友制作一个使用 JPA(EclipseLink) 访问 SQLite 数据库的桌面应用程序。
我已经在 Eclipse 中创建了数据库和实体。但我还创建了一个名为 UniversalDAO
的类,它是所有实体用来访问和持久化数据库的实用程序类:
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();
为了对所有实体进行分组并在此类中使用它们,我创建了一个名为 Entities
的空接口。
这是其中一个实体的样子:
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;
就像您可以欣赏我不是专业人士一样,我还有很多东西要学。 所以,我想知道这种方法是否正确,或者我是否应该为每个实体设置一个 DAO。
【问题讨论】:
您可能想阅读tutorialspoint.com/design_pattern/… 【参考方案1】:您似乎在尝试发明通用 DAO 模式。如果是这样,那么您基本上是在正确的道路上。
通用 DAO 模式的工作原理如下:
创建一个所有 DAO 都将扩展的通用基类:
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
...
通过扩展 GenericDao
创建具体的 DAO 实现:
public class EntityEmailDao extends GenericDao<EntityEmail, Integer>
// This class may contain operations that are relevant to specific entity:
public E findByEmail(String email) ...
由于GenericDao
是通用的,您不需要让您的实体扩展任何通用接口
这种模式有很多现有的实现,看看,例如,here。
【讨论】:
我喜欢这个主意。由于我所有的实体都会做几乎相同的事情,重复的道类是不好的。拥有一个抽象类,然后每个实体都有一个类来扩展该抽象类,这是正确的做法。每一道都有共同的行为和特定的行为。我会这样做的,非常感谢;)以上是关于JPA:所有实体一个 DAO,还是每个实体一个 DAO?的主要内容,如果未能解决你的问题,请参考以下文章
java web spring jpa 在以接口为dao的方法里使用原生sql,联合查找没有对应实体,用啥来接收? 求大神