接口的泛型、通配符和超级/扩展
我有以下 jpa 实体继承层次结构:
- 抽象 Account
- ChildminderAccount 扩展 Account
- ParentAccount 扩展 Account
我希望与我的 DAO 接口具有相同类型的继承层次结构,即三个接口:
- AccountDAO
- ChilminderAccountDAO
- ParentAccountDAO
例如,这是我的基本 DAO 接口,它将保存ChilminderAccountDAO 和 ParentAccountDAO 接口共有的方法:
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import com.bignibou.domain.Account;
public interface AccountDAO extends CrudRepository<Account, Integer> {
@Modifying
@Transactional
@Query("UPDATE Account a SET a.accountValidated = false WHERE a.accountToken = ?1")
int deactivateAccountFromToken(String accountToken);
@Modifying
@Transactional
@Query("UPDATE Account a SET a.accountValidated = true WHERE a.accountToken = ?1")
int reactivateAccountFromToken(String accountToken);
@Query("SELECT COUNT(a) FROM Account a WHERE a.accountEmailAddress = :accountEmailAddress")
long checkIfEmailAddressAlreadyExists(@Param("accountEmailAddress") String accountEmailAddress);
Account findByAccountToken(@Param("accountToken") String accountToken);
Account findByAccountEmailAddress(@Param("accountEmailAddress") String accountEmailAddress);
}
然后我尝试定义我的 ChildminderDAO 接口,如下所示: 公共接口 ChildminderAccountDAO 扩展了 CrudRepository, AccountDAO
结果是:
ChildminderAccountDAO 类型无法扩展或实现 CrudRepository。超类型可以不指定 任何通配符
: 公共接口 ChildminderAccountDAO 扩展了 CrudRepository
,结果是:
接口 CrudRepository 不能多次实现 不同的参数:CrudRepository 和 CrudRepository
None 工作,我不确定如何为我的子接口指定泛型/通配符,以便我在超级接口中保留通用的方法,并允许子接口使用各自类型的实体,即 ChildminderAccount 和 ParentAccount 。
谁能告诉我如何定义我的子接口?
I have the following jpa entity inheritance hierarchy:
- abstract Account
- ChildminderAccount extends Account
- ParentAccount extends Account
I would like to have the same kind of inheritance hierarchy with my DAO interfaces i.e. three intefaces:
- AccountDAO
- ChilminderAccountDAO
- ParentAccountDAO
Here is for instance my base DAO interface which will hold methods common to both ChilminderAccountDAO and ParentAccountDAO interfaces:
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import com.bignibou.domain.Account;
public interface AccountDAO extends CrudRepository<Account, Integer> {
@Modifying
@Transactional
@Query("UPDATE Account a SET a.accountValidated = false WHERE a.accountToken = ?1")
int deactivateAccountFromToken(String accountToken);
@Modifying
@Transactional
@Query("UPDATE Account a SET a.accountValidated = true WHERE a.accountToken = ?1")
int reactivateAccountFromToken(String accountToken);
@Query("SELECT COUNT(a) FROM Account a WHERE a.accountEmailAddress = :accountEmailAddress")
long checkIfEmailAddressAlreadyExists(@Param("accountEmailAddress") String accountEmailAddress);
Account findByAccountToken(@Param("accountToken") String accountToken);
Account findByAccountEmailAddress(@Param("accountEmailAddress") String accountEmailAddress);
}
I then tried to define my ChildminderDAO interface as follows:public interface ChildminderAccountDAO extends CrudRepository<? super Account, Integer>, AccountDAO
which results in:
The type ChildminderAccountDAO cannot extend or implement
CrudRepository. A supertype may not specify
any wildcard
I also tried:public interface ChildminderAccountDAO extends CrudRepository<ChildminderAccount, Integer>, AccountDAO
which results in:
The interface CrudRepository cannot be implemented more than once with
different arguments: CrudRepository and
CrudRepository
None works and I am not sure how to specify the generics/wildcards for my sub-interfaces so that I keep the methods common to both in the super interface and allow the sub interfaces to work with their respective types of entity i.e. ChildminderAccount and ParentAccount.
Can anyone please let me know how to define my sub interfaces?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编译器非常清楚这里出了什么问题(这是一个很好的改变!)。
您的第一次尝试是非法的,因为您无法扩展通配符类型。
您的第二次尝试是非法的,因为您不能使用不同的类型绑定两次继承通用接口。请注意,您的
ChildminderAccountDAO
将扩展CrudRepository
和AccountDAO
,并且AccountDAO
本身扩展CrudRepository<帐户,整数>
。您需要使用的方法是使AccountDAO 本身在帐户类型上通用。它可以在其 extends 子句中使用其类型变量,以一般地扩展
CrudRepository
。然后,子类可以将该类型参数绑定到确定的类型。喜欢:The compiler is being fairly clear about what's wrong here (which makes a nice change!).
Your first attempt is illegal because you can't extend a wildcarded type.
Your second attempt is illegal because you can't inherit a generic interface twice with different type bindings. Note that your
ChildminderAccountDAO
would extend bothCrudRepository<ChildminderAccount, Integer>
andAccountDAO
, andAccountDAO
itself extendsCrudRepository<Account, Integer>
.The approach you need to use is to make
AccountDAO
itself generic on the type of the account. It can use its type variable in its extends clause, to extendCrudRepository
generically. The subclasses can then bind that type parameter to definite types. Like: