这是对以下内容的后续操作:my previous question
我的以下代码行不起作用:
IAccount account = (AccountModel) new AccountRepository().getByEmail(emailaddress);
...getByEmail(...)
的返回类型是Model<Account>
,而AccountModel
扩展了Model<Account>
。然而,当我测试它时,我得到一个
java.lang.ClassCastException: models.Model cannot be cast to models.AccountModel
。我知道这是因为每个AccountModel
都是一个Model<Account>
,而不是相反。有什么方法可以确保我可以解决此问题(或解决它)。
public class AccountRepository extends Repository<Account> {
public AccountRepository() {
super(Account.class);
}
public Model<Account> getByEmail(String emailAddress) {
return this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'");
}
}
public abstract class Repository<T> implements Serializable {
protected final Model<T> getCustomHqlSingle(String hql) {
List<Model<T>> t = this.getCustomHqlList(hql);
if (t != null && !t.isEmpty()) {
return t.get(0);
} else {
return null;
}
}
protected final List<Model<T>> getCustomHqlList(String hql) {
Session session = SESSION_FACTORY.openSession();
try {
session.beginTransaction();
List<T> entities = session.createQuery(hql).getResultList();
List<Model<T>> result = new ArrayList<>();
for (T t : entities) {
result.add(this.getByEntity(t));
}
return result;
} finally {
session.close();
}
}
对于将此问题标记为重复的人,让我从我的问题中改写以下句子:
我知道这是因为每个
AccountModel
都是一个Model<Account>
,但是并非相反。
至
我知道这是因为每个
Dog
都是一个Animal
,而不是另一个的方式。
最佳答案
您必须设计一种将Model<Account>
转换为AccountModel
的方法。从另一个问题中获取代码,您可以为此添加一个构造函数到AccountModel
类中:
public class AccountModel extends Model<Account> implements IAccount {
private static final AccountRepository REPOSITORY = new AccountRepository();
public AccountModel(Account entity) {
super(entity, REPOSITORY);
}
public AccountModel(Model<Account> model) { // <---
super(model._entity, REPOSITORY);
}
// Method implementations...
}
然后更改您的
AccountRepository
类以从AccountModel
返回getByEmail
:public AccountModel getByEmail(String emailAddress) {
return new AccountModel(this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'"));
}
使用新的构造函数将
Model<Account>
转换为AccountModel
。还有另一种选择。您可以让实现类实现一个抽象方法,该方法将返回所需的
new Model<T>(...)
类型,而不是在Repository
中调用Model
:public abstract class Repository<T, R> implements Serializable
...
public Repository(Class<T> repositoryClass) {
if (!Repository._initiated)
setup();
this.cons = cons;
}
protected abstract R getModel(T entity, Repository<T> repo); // <--
然后在工厂方法中的某个位置:
public R getByFoo(...) {
...
T t = session.get(_repositoryClass, ...);
return getModel(t, this);
}
AccountRepository
将返回新的AccountModel
的位置:public class AccountRepository extends Repository<Account, AccountModel> {
public AccountRepository() {
super(Account.class);
}
@Override
protected AccountModel getModel(Account entity, Repository<Account> repo) {
return new AccountModel(entity);
}
}