Java 单道&;通用CRUD方法(JPA/Hibernate+;Spring)

Java 单道&;通用CRUD方法(JPA/Hibernate+;Spring),java,jpa,crud,dao,genericdao,Java,Jpa,Crud,Dao,Genericdao,在我前面的问题之后,我决定在使用JPA/Hibernate、Spring和Wicket的应用程序中为我的数据层(至少在开始时)只使用一个DAO。有人提议使用通用CRUD方法,但我不太确定如何使用JPA实现这一点。你能给我一个例子或分享一个关于这个的链接吗?这里是一个示例界面: public interface GenericDao<T, PK extends Serializable> { T create(T t); T read(PK id); T upd

在我前面的问题之后,我决定在使用JPA/Hibernate、Spring和Wicket的应用程序中为我的数据层(至少在开始时)只使用一个DAO。有人提议使用通用CRUD方法,但我不太确定如何使用JPA实现这一点。你能给我一个例子或分享一个关于这个的链接吗?

这里是一个示例界面:

public interface GenericDao<T, PK extends Serializable> {
    T create(T t);
    T read(PK id);
    T update(T t);
    void delete(T t);
}
公共接口GenericDao{
T创建(T);
T读取(pkid);
T更新(T);
无效删除(T);
}
以及一项实施:

public class GenericDaoJpaImpl<T, PK extends Serializable> 
    implements GenericDao<T, PK> {

    protected Class<T> entityClass;

    @PersistenceContext
    protected EntityManager entityManager;

    public GenericDaoJpaImpl() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass()
             .getGenericSuperclass();
        this.entityClass = (Class<T>) genericSuperclass
             .getActualTypeArguments()[0];
    }

    @Override
    public T create(T t) {
        this.entityManager.persist(t);
        return t;
    }

    @Override
    public T read(PK id) {
        return this.entityManager.find(entityClass, id);
    }

    @Override
    public T update(T t) {
        return this.entityManager.merge(t);
    }

    @Override
    public void delete(T t) {
        t = this.entityManager.merge(t);
        this.entityManager.remove(t);
    }
}
公共类GenericDaoJpaImpl
实现GenericDao{
保护类实体类;
@持久上下文
受保护的实体管理器实体管理器;
公共通用DAOJPAIMPL(){
ParameteredType genericSuperclass=(ParameteredType)getClass()
.getGenericSuperclass();
this.entityClass=(类)genericSuperclass
.getActualTypeArguments()[0];
}
@凌驾
公共T创建(T){
this.entityManager.persist(t);
返回t;
}
@凌驾
公共T读(主键id){
返回此.entityManager.find(entityClass,id);
}
@凌驾
公共T更新(T){
返回此.entityManager.merge(t);
}
@凌驾
公共作废删除(T){
t=this.entityManager.merge(t);
此.entityManager.remove(t);
}
}

如果您正在寻找第三方实现,可以检查
. 它是一个基于注释的通用DAO框架,支持JPA和hibernate

我也在寻找同样的东西。我发现了似乎正是这样的东西——SpringSource提供的JPA项目。这是一个来自Spring的代码端口,现在(2011年初)被Spring吞并,集成度更高。 它允许您将单个dao(SimpleParepository)与静态create一起使用,或者扩展基本JpaRepository类以使用现成的CRUD+方法创建任何特定于对象的dao。还允许类似grails的查询,只需在接口中使用params名称作为方法名称(无需实现!),即
findByLastname(String lastName)
看起来很有希望——成为Spring项目的一部分肯定也会确保它的未来。
我现在已经开始在我即将到来的项目中实现这一点。

基于我们多年来使用这种技术的文章。当我们意识到自己犯了一个大错误后,我们总是与模式的问题作斗争

通过使用诸如Hibernate或JPA之类的ORM工具,您将不必单独考虑DAO和服务层。您可以从服务类中使用EntityManager,因为您知道事务的生命周期和实体类的逻辑

如果调用
myDao.saveEntity
而不是简单地调用
entityManager.saveEntity
,是否节省了时间?不需要。您将有一个不必要的dao类,它除了作为EntityManager的包装器外,不做任何其他事情。在EntityManager(或hibernate中的会话)的帮助下,不要害怕在服务类中写入选择


还有一点需要注意:您应该定义服务层的边界,不要让程序员返回或等待实体类。UI或WS层程序员不应该只知道DTO-s的实体类。实体对象具有大多数程序员不知道的生命周期。如果您将实体对象存储在会话数据中,并在几秒钟或几小时后尝试将其更新回数据库,您将遇到非常严重的问题。您可能不会这样做,但是一个知道服务层的参数类型和返回类型的UI程序员只会保存一些代码行

相关代码可以在github上找到


它集成了Spring和Hibernate和EclipseLink的配置示例

这如何与slsb和pojo实体(表示db表)相适应?回答得很好。只是一些注释:我宁愿将类作为构造函数方法中的参数传递(而不是未检查的强制转换);delete方法中的参数t不应该被重新分配,类最好是抽象的。我尝试按照这个例子,但是
ParameteredType genericSuperclass=(ParameteredType)getClass().getGenericSuperclass()
code正在抛出
java.lang.ClassCastException
,并显示以下消息:
java.lang.Class无法转换为java.lang.reflect.ParameterizedType
有人知道如何修复此问题吗?谢谢,为什么没有交易?我的意思是
entityManager.getTransaction().begin()
entityManager.getTransaction().commit()@wold如果使用JTA,您不需要调用所有这些方法,事实上,如果您尝试在JTA上下文中调用这些方法,IIRC将引发异常。EJB中的带注释的事务管理?!尽管您可能需要更复杂的DAO,它将不再是通用的,但无论如何。我仍然发现这种方法在特定情况下是有用的。