接口的泛型、通配符和超级/扩展

bal*_*teo 2 generics entity interface wildcard

我有以下 jpa 实体继承层次结构:

  • 抽象帐户
  • ChildminderAccount 扩展帐户
  • ParentAccount 扩展帐户

我希望与我的 DAO 接口具有相同类型的继承层次结构,即三个接口:

  • 账户DAO
  • ChilminderAccountDAO
  • 父账户DAO

例如,这是我的基本 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);
}
Run Code Online (Sandbox Code Playgroud)

然后我尝试如下定义我的 ChildminderDAO 接口: public interface ChildminderAccountDAO extends CrudRepository<? super Account, Integer>, AccountDAO这导致:

ChildminderAccountDAO 类型不能扩展或实现 CrudRepository。超类型不能指定任何通配符

我也试过: public interface ChildminderAccountDAO extends CrudRepository<ChildminderAccount, Integer>, AccountDAO结果是:

CrudRepository 接口不能用不同的参数多次实现:CrudRepository 和 CrudRepository

没有任何作用,我不确定如何为我的子接口指定泛型/通配符,以便我在超级接口中保留两者通用的方法,并允许子接口使用它们各自类型的实体,即 ChildminderAccount 和 ParentAccount。

谁能让我知道如何定义我的子接口?

Tom*_*son 5

编译器很清楚这里出了什么问题(这是一个很好的改变!)。

您的第一次尝试是非法的,因为您无法扩展通配符类型。

您的第二次尝试是非法的,因为您不能使用不同的类型绑定两次继承通用接口。请注意,您ChildminderAccountDAO将同时扩展CrudRepository<ChildminderAccount, Integer>AccountDAO,并且AccountDAO本身也扩展了CrudRepository<Account, Integer>

您需要使用的方法是使AccountDAO自己在帐户类型上具有通用性。它可以在其 extends 子句中使用其类型变量来进行泛型扩展CrudRepository。然后子类可以将该类型参数绑定到确定的类型。喜欢:

public interface AccountDAO<A extends Account> extends CrudRepository<A, Integer>

public interface ChildminderAccountDAO extends AccountDAO<ChildminderAccount>

public interface ParentAccountDAO extends AccountDAO<ParentAccount>
Run Code Online (Sandbox Code Playgroud)