【问题标题】:How can I wrap Play/JPA's Model class with a generic Repository?如何用通用存储库包装 Play/JPA 的模型类?
【发布时间】:2011-11-16 12:41:11
【问题描述】:

我不喜欢直接使用模型对象,因为这会破坏封装。相反,我更喜欢Repository Pattern

当我尝试实现一个简单的存储库时

public abstract class BaseRepository<T extends Model> {
    public T findOne(String query, Object... params) {
        GenericModel.JPAQuery result = T.find(query, params);
        return result.first();
    }
}
public class UserRepository extends BaseRepository<User>{}

UserRepository repo = new UserRepository();
repo.findOne("byUsername", "test");

由于 java 的泛型或 JPA 注释的工作方式,我得到了异常:

java.lang.UnsupportedOperationException: Please annotate your JPA model with 
@javax.persistence.Entity annotation.
    at play.db.jpa.GenericModel.find(GenericModel.java:269)
    at repositories.BaseRepository.findOne(BaseRepository.java:12)

有没有办法解决这个问题?

(不用说模型已正确注释,当我直接使用它时说 User.find("byUsername", "test").first() 效果很好)。

【问题讨论】:

  • 您能否提供实际调用findOne() 并引发异常的代码示例?
  • @pHk - UserRepository repo = new UserRepository(); repo.findOne("byUsername", "testy");
  • 这很奇怪。恐怕我现在没有太多帮助了,但我真的很好奇为什么这会导致对GenericModel 的静态调用。
  • @pHk - 好的,感谢您的帮助。那你可以删除你的答案吗,因为它不是很相关?

标签: java jpa persistence playframework repository-pattern


【解决方案1】:

它不起作用,因为您正在调用静态(类)方法。

JPAEnhancer 会在运行时将方法添加到您的类(用户)中,但类型/静态方法没有多态性,它将始终调用 GenericModel。

您可以尝试做的是使用类似

的方式获取实际的参数类型
ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
Class<?> aClass = (Class<?>) ((ParameterizedType) superclass).getActualTypeArguments()[0];

以及该类的调用方法..

希望对您有所帮助...

【讨论】:

  • 这是我在你回答后尝试的代码:gist.github.com/1370600 我在调用 invoke() 方法时遇到argument type mismatch 异常 - 也许它与方法中的省略号有关论据。无论如何,目前我的应用程序似乎有点矫枉过正。
  • 不错。类型转换中的泛型类型约束实际上没有编译,所以我放弃了它。这是一个完整的工作示例 - gist.github.com/1370851
猜你喜欢
  • 2018-12-03
  • 2014-02-20
  • 1970-01-01
  • 2018-06-15
  • 1970-01-01
  • 2017-08-26
  • 2021-07-23
  • 1970-01-01
  • 2021-02-19
相关资源
最近更新 更多