我有一个工作的“请求工厂”示例,我想重构它,以便我可以将“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
}
我的新Request对象如下所示。我将“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()的域方法”for persist()和remove() - 方法。为什么EntityLocator中的查找不起作用?我需要ServiceLocator吗?我没有完全理解谷歌教程,并且链接的示例不再可用。
答案 0 :(得分: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模式。这就是我透明的持久层所针对的。但是,Locator的使用需要一个额外的类来放入persist,remove和findX方法。它们称之为数据访问对象(实际上是它),我宁愿称之为管理器。
TL;博士
您尝试放入定位器的方法不会去那里。你需要一个额外的课程(称之为DAO或经理)。
在RequestContext中使用DAO / Manager作为服务
答案 1 :(得分:0)
我认为您不能将persist
和remove
方法放在定位器中。该文档不建议您可以向定位器接口添加任意方法并从客户端引用它们。如果您只是想避免在每个实体类中重复persist
和remove
方法,那么您可以将它们放在EntityBase
类中。我做到了这一点,效果很好。
如果您还想避免重复每个请求接口中的函数,可以像这样制作通用基类Request:
@SkipInterfaceValidation
public interface BaseEntityRequest<P extends EntityProxy> extends RequestContext {
InstanceRequest<P, Void> persist();
InstanceRequest<P, Void> remove();
}
并像这样使用它:
public interface ArticleRequest extends BaseEntityRequest<ArticleRequest> {
...
}
答案 2 :(得分:0)
尽管persist()
和remove()
在定位器中是有意义的,因此实体对持久层完全不可知,但当前的RF api不支持此功能。因此,您必须处理将这些方法添加到BaseEntity
并找出在定位器中调用persist方法的方法。
我认为您可以打开一个需要此功能的gwt问题。
避免在实体中使用某些方法的另一种方法是使用ValueProxy
代替EntityProxy
,但在这种情况下,您必须提供从客户端保存/删除这些对象的方法。
答案 3 :(得分: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);
}
}