我想知道,是否可以将请求工厂代理/上下文的泛型类用于所有实体的常见操作,例如getById(Long id)
。
在我的应用程序中,我将有许多类,如类,只有id
和name
参数,所以我想写一次功能,并通过继承类中的继承使用它:
以下是服务器实施:
域模型类
@MappedSuperclass
public class GenericModel<T extends GenericModel<T>> implements Identifiable, Versionable {
@Transient
protected Class<T> entityClass;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
// setter & getter
@Override
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
@Override
public Integer getVersion() {return version;}
public void setVersion(Integer version) {this.version = version;}
// constructor
public GenericModel() {
Class<?> obtainedClass = getClass();
Type genericSuperclass = null;
for (;;) {
genericSuperclass = obtainedClass.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
break;
}
obtainedClass = obtainedClass.getSuperclass();
}
ParameterizedType genericSuperclass_ = (ParameterizedType) genericSuperclass;
try {
entityClass = ((Class) ((Class) genericSuperclass_
.getActualTypeArguments()[0]));
} catch (ClassCastException e) {
entityClass = guessEntityClassFromTypeParametersClassTypedArgument();
}
}
public GenericModel(Long id) {
this();
this.id = id;
}
}
@MappedSuperclass
public abstract class GenericDictionaryModel<T extends GenericModel<T>> extends GenericModel<T> {
private String name;
@Transient
private String optionDisplayName;
// private boolean active = true;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
// public boolean getActive() {return active;}
// public void setActive(boolean stat) {this.active = stat;}
public String getOptionDisplayName() {return optionDisplayName;}
public void setOptionDisplayName(String optionDisplayName) {this.optionDisplayName = optionDisplayName;}
public GenericDictionaryModel() {
super();
}
public GenericDictionaryModel(Long id, String name) {
super(id);
this.name = name;
}
}
@Entity
public class PageI extends GenericDictionaryModel<PageI> {
@ManyToMany(cascade = CascadeType.ALL)
private List<Content> contents;
/* Getters and Setters */
public List<Content> getContents() {
return contents;
}
public void setContents(List<Content> contents) {
this.contents = contents;
}
}
DAO课程
public class GenericDao<T extends GenericModel<T>> {
private Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());
@Transient protected Class<T> entityClass;
public GenericDao() {
super();
}
public GenericDao(Class<? extends GenericModel<T>> clazz) {
this.entityClass = (Class<T>) clazz;
}
public T getBy(Long id) {
return JPA.em().find(entityClass, id);
}
public List<GenericModel<T>> get() {
logger.error("trying to get data from db");
return getList();
}
// public List<T> get() {
// }
public List<GenericModel<T>> getList() {
List<T> resultList = JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();
logger.error(resultList.toString());
return JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();
}
}
public class GenericDictionaryDao<T extends GenericDictionaryModel<T>> extends GenericDao<T>{
private Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());
// public T getBy(Long id) {
// return super.getBy(id);
// }
public List<GenericModel<T>> getByName() {
return super.get();
}
// public List<T> getListOrderedByName() {
// public List<GenericDictionaryModel> getListOrderedByName() {
public List<GenericDictionaryModel> getListOrderedByName2() {
return null;
}
public List<GenericDictionaryModel<T>> getListOrderedByName() {
try {
return JPA.em()
.createQuery("FROM " + entityClass.getSimpleName() + " ORDER BY name")
.getResultList();
} catch (ClassCastException e) {
return new LinkedList<GenericDictionaryModel<T>>();
}
// return null;
}
}
以下是共享实施:
代理:
@ProxyFor(value = GenericModel.class, locator = GenericLocator.class)
public interface GenericProxy extends EntityProxy {
public Long getId();
public void setId(Long id);
public Integer getVersion();
public void setVersion(Integer version);
}
@ProxyFor(value = GenericDictionaryModel.class, locator = GenericLocator.class)
public interface GenericDictionaryProxy extends GenericProxy {
public String getName();
public void setName(String name);
}
@ProxyFor(value = PageI.class, locator = GenericLocator.class)
public interface PageIProxy extends GenericDictionaryProxy {
public List<ContentIProxy> getContents();
public void setContents(List<ContentIProxy> contents);
public static final String Contents = "contents";
}
上下文/服务:
@Service(value = GenericDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
GenericProxy.class
} )
public interface GenericContext extends RequestContext {
Request<GenericProxy> getBy(Long id);
Request<List<GenericProxy>> get();
Request<Void> save(GenericProxy entity);
}
@Service(value = GenericDictionaryDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
GenericDictionaryProxy.class,
PageIProxy.class,
ContentIProxy.class
} )
public interface GenericDictionaryContext extends GenericContext {
public Request<List<GenericDictionaryProxy>> getListOrderedByName();
}
public interface Services extends RequestFactory {
GenericContext getGenericContext();
GenericDictionaryContext getGenericDictionaryContext();
}
这是客户端执行实现:
List<GenericDictionaryProxy> proxies = new LinkedList<GenericDictionaryProxy>();
GenericDictionaryContext context = createRequestFactory().getGenericDictionaryContext();
context.get().to(new Receiver<List<GenericDictionaryProxy>>() {
@Override
public void onSuccess(List<GenericDictionaryProxy> response) {
for(GenericDictionaryProxy p: response) {
cont.add(new Label(p.getId() + " " + p.getName() + ", " + p.getVersion() ));
}
}
}).fire();
哪个应该返回一个带参数的对象列表:id,version,name。
不幸的是它起作用了。
我的IDE显示错误:
Could not find domain method similar to java.util.List<pl.derp.server.model.GenericDictionaryModel<T>> getListOrderedByName() GenericDictionaryContext.java /Index/src/main/java/pl/derp/shared/rf line 26 Annotation Problem (Java 6 processor)
The method to(Receiver<? super List<GenericProxy>>) in the type Request<List<GenericProxy>> is not applicable for the arguments (new Receiver<List<GenericDictionaryProxy>>(){}) GoodbyeViewImpl.java /Index/src/main/java/pl/derp/client/view line 91 Java Problem
以下是编译错误:
[INFO] Tracing compile failure path for type 'pl.derp.client.view.GoodbyeViewImpl'
[INFO] [ERROR] Errors in 'file:/home/korbeldaniel/git/derp3/tutorial/src/main/java/pl/derp/client/view/GoodbyeViewImpl.java'
[INFO] [ERROR] Line 91: The method to(Receiver<? super List<GenericProxy>>) in the type Request<List<GenericProxy>> is not applicable for the arguments (new Receiver<List<GenericDictionaryProxy>>(){})
[INFO] [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
请告诉我我做错了什么。
答案 0 :(得分:1)
是的,这对您有用,但您需要在RequestContext上为所需的所有不同类型添加@ExtraTypes注释。
我不久前发布了一个完整的例子。
GWT polymorphic lists with @ExtraTypes
修改强>
要使其工作,您应该使您的通用请求上下文使用泛型。这是我过去所做的,它对我来说是正确的。你不会需要通用的额外类型来使这项工作,因为你将告诉它类型。
@Service(value = GenericDao.class, locator = MyServiceLocator.class)
public interface GenericContext<T extends GenericProxy> extends RequestContext {
Request<T> getBy(Long id);
Request<List<T>> get();
Request<Void> save(T entity);
}
@Service(value = GenericDictionaryDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
GenericDictionaryProxy.class,
PageIProxy.class,
ContentIProxy.class
} )
public interface GenericDictionaryContext extends GenericContext<GenericDictionaryProxy> {
public Request<List<GenericDictionaryProxy>> getListOrderedByName();
// These used to be required due to a bug a while ago. Test without it
// but if you get a method about an unknown method then this is the issue.
Request<GenericDictionaryProxy> getBy(Long id);
Request<List<GenericDictionaryProxy>> get();
Request<Void> save(T entity);
}
前一段时间我发现了一个问题,不确定它是否已修复但我还必须将这些方法添加到扩展类中。我不介意因为我仍然被允许在需要时使用我的GenericContext并且一切正常。这允许我使用番石榴LoadingCache创建一个很好的实体缓存机制。
简单示例。
public class EntityCache<T extends GenericProxy, R extends GenericContext<T>> {
private R requestContext;
public EntityCache(R requestContext) {
this.requestContext = requestContext;
}
public T get(Long key) {
// get from loading cache but this is a simple example.
requestContext.get(key);
}
}