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

发布于 2025-01-07 16:27:32 字数 2142 浏览 1 评论 0原文

我有以下 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, AccountDAO ,结果是:

接口 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

早茶月光 2025-01-14 16:27:32

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

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

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

您需要使用的方法是使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>

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 both CrudRepository<ChildminderAccount, Integer> and AccountDAO, and AccountDAO itself extends CrudRepository<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 extend CrudRepository generically. The subclasses can then bind that type parameter to definite types. Like:

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

public interface ChildminderAccountDAO extends AccountDAO<ChildminderAccount>

public interface ParentAccountDAO extends AccountDAO<ParentAccount>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文