Java Hibernate:CRUD 通用 DAO
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9721383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate: CRUD Generic DAO
提问by Fabio B.
My web application has got a lot of service tables/entities, such as payment_methods
, tax_codes
, province_codes
, etc.
我的web应用程序已经得到了很多服务表/实体,如payment_methods
,tax_codes
,province_codes
,等。
Each time I add a new entity, I have to write a DAO. The thing is that, basically, they are all the same, but the only difference is the entity class itself.
每次添加新实体时,我都必须编写一个 DAO。问题是,基本上,它们都是相同的,但唯一的区别是实体类本身。
I know that Hibernate tools can generate the code for me automatically but I can't use them now (don't ask why) so I'm thinking of a Generic DAO. There's a lot of literature about that but I can't put pieces together and make it work with Spring.
我知道 Hibernate 工具可以自动为我生成代码,但我现在不能使用它们(不要问为什么)所以我在考虑Generic DAO。有很多关于这方面的文献,但我无法将各个部分放在一起并使其与 Spring 一起使用。
It's all about generics I think, it will have four basic methods:
我认为这都是关于泛型的,它将有四个基本方法:
listAll
saveOrUpdate
deleteById
getById
listAll
saveOrUpdate
deleteById
getById
and that's all.
就这样。
Question:
题:
What's the best practicefor not re-inventing the wheel? Isn't there something ready to use, yet?
不重新发明轮子的最佳做法是什么?不是有什么可以使用的吗?
采纳答案by NimChimpsky
here's mine
这是我的
@Component
public class Dao{
@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
public <T> T save(final T o){
return (T) sessionFactory.getCurrentSession().save(o);
}
public void delete(final Object object){
sessionFactory.getCurrentSession().delete(object);
}
/***/
public <T> T get(final Class<T> type, final Long id){
return (T) sessionFactory.getCurrentSession().get(type, id);
}
/***/
public <T> T merge(final T o) {
return (T) sessionFactory.getCurrentSession().merge(o);
}
/***/
public <T> void saveOrUpdate(final T o){
sessionFactory.getCurrentSession().saveOrUpdate(o);
}
public <T> List<T> getAll(final Class<T> type) {
final Session session = sessionFactory.getCurrentSession();
final Criteria crit = session.createCriteria(type);
return crit.list();
}
// and so on, you shoudl get the idea
and you can then access like so in service layer:
然后您可以在服务层中像这样访问:
@Autowired
private Dao dao;
@Transactional(readOnly = true)
public List<MyEntity> getAll() {
return dao.getAll(MyEntity.class);
}
回答by Tomasz Nurkiewicz
Spring Data JPAis a wonderful project that generate DAOs for you, and more! You only have to create an interface (without any implementation):
Spring Data JPA是一个很棒的项目,可以为您生成 DAO,等等!您只需要创建一个接口(无需任何实现):
interface PaymentMethodsDao extends JpaRepository<PaymentMethods, Integer> {}
This interface (via inherited JpaRepository
) will automatically give you:
这个接口(通过继承JpaRepository
)会自动给你:
PaymentMethod save(PaymentMethod entity);
Iterable<PaymentMethod> save(Iterable<? extends PaymentMethod> entities);
PaymentMethod findOne(Integer id);
boolean exists(Integer id);
Iterable<PaymentMethod> findAll();
long count();
void delete(Integer id);
void delete(PaymentMethod entity);
void delete(Iterable<? extends PaymentMethod> entities);
void deleteAll();
Iterable<PaymentMethod> findAll(Sort sort);
Page<PaymentMethod> findAll(Pageable pageable);
List<PaymentMethod> findAll();
List<PaymentMethod> findAll(Sort sort);
List<PaymentMethod> save(Iterable<? extends PaymentMethods> entities);
void flush();
PaymentMethod saveAndFlush(PaymentMethods entity);
void deleteInBatch(Iterable<PaymentMethods> entities);
The interface is strongly typed (generics) and automatically implemented for you. For every entity all you have to do is to create an interface extending JpaRepository<T,Integer extends Serializable>
.
该接口是强类型(泛型)并自动为您实现。对于每个实体,您所要做的就是创建一个扩展JpaRepository<T,Integer extends Serializable>
.
But wait, there's more! Assuming your PaymentMethod
has name
and validSince
persistent fields. If you add the following method to your interface:
但是等等,还有更多!假设您的PaymentMethod
hasname
和validSince
persistent 字段。如果您将以下方法添加到您的界面:
interface PaymentMethodsDao extends JpaRepository<PaymentMethods, Integer> {
Page<PaymentMethod> findByNameLikeAndValidSinceGreaterThan(
String name, Date validSince, Pageable page
);
}
the framework will parse the method name:
框架将解析方法名称:
findBy
(Namelike) And
(ValidSincegreater than)
findBy
( Namelike) And
( ValidSince大于)
create the JPA QL query, apply paging and sorting (Pageable page
) and run it for you. No implementation needed:
创建 JPA QL 查询,应用分页和排序 ( Pageable page
) 并为您运行它。不需要实现:
paymentMethodsDao.findByNameLikeAndValidSinceGreaterThan(
"abc%",
new Date(),
new PageRequest(0, 20, Sort.Direction.DESC, "name"
);
Resulting query:
结果查询:
SELECT * //or COUNT, framework also returns the total number of records
FROM PaymentMethods
WHERE name LIKE "abc%"
AND validSince > ...
And with paging applied.
并应用分页。
The only downside is that the project is rather new and it is relatively easy to hit buts (but it is very actively developed).
唯一的缺点是这个项目比较新,比较容易打不过(但开发非常积极)。
回答by AlexR
Do not write specific dao for each entity. You can implement one generic DAO that does 90% of work for all entities you need. You can extend it in cases you want specific treatment of certain entities.
不要为每个实体编写特定的 dao。您可以实现一个通用 DAO,它为您需要的所有实体完成 90% 的工作。如果您想要对某些实体进行特定处理,您可以扩展它。
In project I am currently working on we have such DAO that wraps Hibernate session providing methods similar to those that you described. Moreover we are using ISearch API - the open source project hosted at google code and providing very convenient criteria building interface for Hibernate and JPA.
在我目前正在研究的项目中,我们有这样的 DAO,它包装了 Hibernate 会话,提供类似于您描述的方法。此外,我们正在使用 ISearch API——谷歌代码托管的开源项目,并为 Hibernate 和 JPA 提供非常方便的标准构建界面。
回答by Shahid Yousuf
you can use Generic DAO as leverage for other Domain specific DAO classes. Suppose you have an Employee Domain class as:
您可以使用通用 DAO 作为其他领域特定 DAO 类的杠杆。假设您有一个 Employee Domain 类:
@Entity
@Table(name="employee")
public class Employee {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="emp_name")
private String empName;
@Column(name="emp_designation")
private String empDesignation;
@Column(name="emp_salary")
private Float empSalary;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpDesignation() {
return empDesignation;
}
public void setEmpDesignation(String empDesignation) {
this.empDesignation = empDesignation;
}
public Float getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Float empSalary) {
this.empSalary = empSalary;
}
}
then the required generic DAO would look something like this:
那么所需的通用 DAO 将如下所示:
Generic DAO Interface:
通用 DAO 接口:
public interface GenericRepositoryInterface<T> {
public T save(T emp);
public Boolean delete(T emp);
public T edit(T emp);
public T find(Long empId);
}
Generic DAO implementation:
通用 DAO 实现:
@Repository
public class GenericRepositoryImplementation<T> implements GenericRepositoryInterface<T> {
protected EntityManager entityManager;
private Class<T> type;
public GenericRepositoryImplementation() {
// TODO Auto-generated constructor stub
}
public GenericRepositoryImplementation(Class<T> type) {
// TODO Auto-generated constructor stub
this.type = type;
}
public EntityManager getEntityManager() {
return entityManager;
}
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public T save(T emp) {
// TODO Auto-generated method stub
entityManager.persist(emp);
entityManager.flush();
return emp;
}
@Override
public Boolean delete(T emp) {
// TODO Auto-generated method stub
try {
entityManager.remove(emp);
} catch (Exception ex) {
return false;
}
return true;
}
@Override
public T edit(T emp) {
// TODO Auto-generated method stub
try{
return entityManager.merge(emp);
} catch(Exception ex) {
return null;
}
}
@Override
public T find(Long empId) {
// TODO Auto-generated method stub
return (T) entityManager.find(Employee.class, empId);
}
}
This generic DAO class then needs to be extended by every Domain specific DAO class. The Domain specific DAO class may even implement another interface for operations that are not common in general. And prefer sending type information using constructor.
这个通用的 DAO 类然后需要被每个领域特定的 DAO 类扩展。特定于域的 DAO 类甚至可以为一般不常见的操作实现另一个接口。并且更喜欢使用构造函数发送类型信息。
回答by Mandar Kawtakwar
you can create a baseDAO Interface and a baseDAO implementation class. And When you need specific use case with different class types you can just create that class's DAO which inherit baseDAO class and implement extra interface with that class's specific needs like this
您可以创建一个 baseDAO 接口和一个 baseDAO 实现类。当您需要具有不同类类型的特定用例时,您可以创建该类的 DAO,它继承 baseDAO 类并实现具有该类特定需求的额外接口,如下所示
IBaseDAO
IBaseDAO
public interface IBaseDAO<T> {
/**
* @Purpose :Save object of type T
* @param transientInstance
*/
public Object persist(final T transientInstance);
/**
* @Purpose :Delete object of type T
* @param persistentInstance
*/
public void remove(final T persistentInstance);
/**
* @Purpose :Update Object of type T
* @param detachedInstance
* @return
*/
public T merge(final T detachedInstance);
/**
* @Purpose :Find object by 'id' of type T
* @param identifier
* @return
*/
public T findById(final Long identifier, Class<?> persistClass);
}
BaseDAO Class
BaseDAO 类
public class BaseDAO<T> implements IBaseDAO<T> {
@Autowired
private SessionFactory sessionFactory;
public Object persist(T entity) {
return this.getSession().save(entity);
}
@Override
public void remove(T persistentInstance) {
this.getSession().delete(persistentInstance);
}
@SuppressWarnings("unchecked")
@Override
public T merge(T detachedInstance) {
return (T) this.getSession().merge(detachedInstance);
}
@SuppressWarnings("unchecked")
@Override
public T findById(Long identifier, Class<?> persistClass) {
return (T) this.getSession().get(persistClass, identifier);
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public Session getSession() {
return getSessionFactory().getCurrentSession();
}
}
and specific interface
和具体接口
public interface IUserDAO extends IBaseDAO<User> {
public User getUserById(long userId);
public User findUserByUsername(String username);
}
and classes like this
和这样的课程
@Repository("userDAO")
public class UserDAO extends BaseDAO<User> implements IUserDAO {
public User getUserById(long userId) {
return findById(userId, User.class);
}
@Override
public User findUserByUsername(String username) {
Criteria criteria = getSession().createCriteria(User.class);
criteria.add(Restrictions.eq("username", username));
return (User) criteria.uniqueResult();
}
}