1

我有一个有效的“请求工厂”示例,我想对其进行重构,以便可以将“persist()”和“remove()”等通用方法从域对象中移出到通用定位器中。目前我有以下(工作)代码:

一个通用超类,包含所有域对象的 id 和版本:

@MappedSuperclass  
public class EntityBase {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    // setter & getter

}

域对象。它有 persist() 和 remove() 方法,我想从类中重构它们:

@Entity
@Table(name = "article")
public class Article extends EntityBase{

    public static Article findArticle(Long id) {
        //find article
    }


    public void persist() {
        // persist
    }

    public void remove() {
        // remove
    }

}

域对象的代理对象:

@ProxyFor(value = Article.class)
public interface ArticleProxy extends EntityProxy {

    // some getter and setters

}

我的域对象的请求对象:

@Service(value = Article.class)
public interface ArticleRequest extends RequestContext {

    Request<ArticleProxy> findArticle(Long id);

    InstanceRequest<ArticleProxy, Void> persist();

    InstanceRequest<ArticleProxy, Void> remove();
}

我的请求工厂:

public interface MyRequestFactory extends RequestFactory {

  ArticleRequest articleRequest();

}

--------------------------------------

现在我的重构代码不再工作了:

我从域对象中删除了 persist() 和 remove() 方法:

@Entity
@Table(name = "article")
public class Article extends EntityBase{

    public static Article findArticle(Long id) {
        //find article
    }

}

我像这样创建了我的定位器,并在此处添加了方法“remove()”和“persist()”(以及其他默认方法):

public class EntityLocator extends Locator<EntityBase, Long> {

    @Override
    public EntityBase create(Class<? extends EntityBase> clazz) {
        try {  
            return clazz.newInstance();  
        } catch (InstantiationException e) {  
            throw new RuntimeException(e);  
        } catch (IllegalAccessException e) {  
            throw new RuntimeException(e);  
        }  
    }

    @Override
    public EntityBase find(Class<? extends EntityBase> clazz, Long id) {
        return null;
    }


    @Override
    public Class<EntityBase> getDomainType() {
        return null;
    }

    @Override
    public Long getId(EntityBase domainObject) {
        return null;
    }

    @Override
    public Class<Long> getIdType() {
        return null;
    }

    @Override
    public Object getVersion(EntityBase domainObject) {
        return null;
    }

    public void persist(EntityBase domainObject){
        // persist something
    }

    public void remove(EntityBase domainObject){
        // remove
    }

}

我的代理对象链接到定位器(locator=EntityLocator.class):

@ProxyFor(value = Article.class, locator=EntityLocator.class)
public interface ArticleProxy extends EntityProxy {

    // getter and setters here

}

我的新请求对象如下所示。我将“InstanceRequests”改为“Requests”,根据我在定位器中的新方法更改了返回类型和参数:

@Service(value = Article.class)
public interface ArticleRequest extends RequestContext {

    Request<ArticleProxy> findArticle(Long id);

    Request<Void> persist(ArticleProxy article);

    Request<Void> remove(ArticleProxy article);

}

但是现在我收到错误“找不到类似于 java.lang.Void persist() 的域方法”,用于 persist() 和 remove() 方法。为什么 EntityLocator 中的查找不起作用?我需要 ServiceLocator 吗?我没有完全理解谷歌教程,并且链接的示例不再可用。

4

4 回答 4

1

我和你有同样的问题。GWTProject.org ( http://www.gwtproject.org/doc/latest/DevGuideRequestFactory.html ) 上的指南对如何正确实现这一点不是很清楚,尽管它是写在字里行间的。

以下教程使我清楚地了解了解决方案:http: //cleancodematters.com/2011/06/04/tutorial-gwt-request-factory-part-i/

对我来说,DAO 一词的使用混淆了事物。我不会使用 DAO 模式。这就是我的透明持久层的用途。但是,使用定位器需要一个额外的类来放置persist、remove 和findX 方法。他们称它为数据访问对象(实际上是),我宁愿称它为Manager。

tl;博士

您尝试放入定位器的方法不会去那里。你需要一个额外的类(称它为 DAO 或 Manager)。

在 RequestContext 中使用 DAO/Manager 作为服务

于 2013-08-23T12:39:35.913 回答
0

您的界面 ArticleRequest 配置不正确。你需要像这样纠正它。

@Service(value = SentenceServiceImpl.class, locator = SpringServiceLocator.class)
public interface SentenceServiceRequest extends RequestContext {

    Request<List<SentenceProxy>> getSentences();

    Request<Void> saveOrUpdate(SentenceProxy sentence);

}

定位器:

public class SpringServiceLocator implements ServiceLocator {

    public Object getInstance(Class<?> clazz) {
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestFactoryServlet.getThreadLocalServletContext());
        return context.getBean(clazz);
    }

}
于 2013-05-30T06:19:58.017 回答
0

I don't think you can place the persist and remove methods in the locator. The documentation doesn't suggest you can add arbitrary methods to the locator interface and reference them from the client. If you just want to avoid duplicating the persist and remove methods in every entity class then you can put them in your EntityBase class. I've done this and it works nicely.

If you also want to avoid repeating the functions in each of your request interfaces, you can make a generic base class Request like so:

@SkipInterfaceValidation
public interface BaseEntityRequest<P extends EntityProxy> extends RequestContext {
    InstanceRequest<P, Void> persist();
    InstanceRequest<P, Void> remove();
}

and use it like so:

public interface ArticleRequest extends BaseEntityRequest<ArticleRequest> {
    ...
}
于 2013-05-29T13:06:22.113 回答
0

尽管它在定位器中是有意义的persist()remove()但由于实体对持久层完全不可知,当前的 RF api 不支持这一点。因此,您必须处理将这些方法添加到您的方法BaseEntity并找出在定位器中调用持久方法的方法。

我认为您可以打开一个需要此功能的 gwt 问题。

避免在实体中使用某些方法的另一种方法是使用ValueProxyinsteadof EntityProxy,但在这种情况下,您必须提供从客户端保存/删除这些对象的方法。

于 2013-05-29T14:11:14.057 回答