如何在基于Wicket,Spring,Hibernate的Web应用程序中正确使用LoadableDetachableModel?

时间:2011-08-11 19:20:35

标签: hibernate spring wicket

我正在开发一个基于Hibernate,Spring和Wicket的Web应用程序。

到目前为止,我实现了业务对象和持久层。该事务由Spring框架的事务拦截器管理。因此,DAO类的每个方法都封装在一个事务中。与单元测试一起实现这一点是直截了当的。

现在我来到Web应用程序部分,我也使用Spring进行依赖注入。与Wicket框架的@SpringBean注释一起,我在Wicket组件中注入了DAO。但是因为我对Wicket很新,所以在传递它们时使用正确的模型为我的业务对象时,我会有点卡住Wicket组件。

我尝试过LoadableDetachableModel但遇到了一些问题。我有一个页面来创建新的或编辑现有的业务对象,具体取决于页面的输入参数。如果参数中有id,则应从数据库加载相应的业务对象。如果没有参数,则应创建新的业务对象。该部分是一个应该被编辑的对象运行得相当好但是当应该创建一个新对象时,我填写Web表单并按下save,我得到一个NullPointerException。经过一些调试后,我发现LoadableDetachableModel无法返回业务对象的实例,因为重写的load()方法无法从数据库加载对象,因为它尚未保存,因此没有id。

所以现在我想知道如何解决这个问题。 LoadableDetachableModel是正确的选择吗?是否可以将表单分成两个相互依赖的形式,每个表单使用不同的模型。因此,只有编辑页面/表单使用LoadableDetachableModel?

2 个答案:

答案 0 :(得分:2)

Igor Vaynberg在the Wicket In Action blog对此及其相关问题作了很好的解释。

该页面的最后一位处理此问题,基本上是由使用LoadableDetachableModel,而是实施AbstractEntityModel,这样可以实现更完整的控制。

答案 1 :(得分:0)

Wicket 6.x Reference Documentation > 11 Wicket models and forms > 11.6 Detachable models将其描述如下:

  

现在作为可能使用LoadableDetachableModel的示例,我们会   构建一个模型,旨在与通过JPA管理的实体一起工作。至   了解以下代码需要JPA的基本知识   即使我们不了解这个标准的细节。

     

以下型号仅供参考,不是   旨在用于生产环境。重要方面如此   因为交易管理没有考虑在内,你应该考虑   在考虑使用它之前重做代码。

public class JpaLoadableModel<T> extends LoadableDetachableModel<T> {

    private EntityManagerFactory entityManagerFactory;
    private Class<T> entityClass;
    private Serializable identifier;
    private List<Object> constructorParams;

    public JpaLoadableModel(EntityManagerFactory entityManagerFactory, T entity) {
        super();

        PersistenceUnitUtil util = entityManagerFactory.getPersistenceUnitUtil();

        this.entityManagerFactory = entityManagerFactory;
        this.entityClass = (Class<T>) entity.getClass();
        this.identifier = (Serializable) util.getIdentifier(entity);

        setObject(entity);
    }

    @Override protected T load() {
        T entity = null;

        if(identifier != null) {
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            entity = entityManager.find(entityClass, identifier);
        }
        return entity;
    }

    @Override protected void onDetach() {
        super.onDetach();

        T entity = getObject();
        PersistenceUnitUtil persistenceUtil = entityManagerFactory.getPersistenceUnitUtil();

        if(entity == null) return;

        identifier = (Serializable) persistenceUtil.getIdentifier(entity);
    }
}
     

模型的构造函数将两个参数作为输入:a   JPA接口的实现   javax.persistence.EntityManagerFactory来管理JPA实体和   必须由此模型处理的实体。在它的构造函数里面   model保存实体的类及其id(如果是,则可以为null)   该实体尚未持久化)。这两个信息是   需要在以后检索实体并由...使用   加载方法。

     

onDetach负责在分离前更新实体ID   发生。 id可以在第一次实体持久化时更改(JPA   生成一个新的id并将其分配给实体)。请注意   此模型不负责保存所发生的任何更改   实体对象在分离之前。如果我们不想放松这些   我们必须在分离之前明确地保留实体   阶段发生。

     

由于此示例的模型包含对EntityManagerFactory的引用,因此使用的实现必须为Serializable