Spring Data Repository with Inheritance.JOINED

wes*_*eyy 6 java inheritance spring hibernate jpa

我在我的应用程序中设计了实体以遵循Hibernate 的继承策略Inheritance.JOINED

基本抽象类是UserTable,具体派生类是ClientTableOwnerTable

我想要实现的目标是拥有一个存储库,我可以在其中通过or 进行find任何UserTableClientTableOwnerTable)。重要的要求是,一旦它们被获取,它们就可以被强制转换为正确的类型,并且它们携带它们的特定字段(而不仅仅是从 继承的那些)。IdEmailUserTable

同样重要的是,我应该能够通过同一个存储库保存这些实体,即。repository.save(clientTable).

所以这样的事情应该是可能的:

UserTableRepository repository = // ...

int clientId = 3; 
int ownerId = 5;

ClientTable clientTable = (ClientTable) repository.findByUserId(clientId);
OwnerTable clientTable = (OwnerTable) repository.findByUserId(ownerId);

clientTable = (ClientTable) repository.findByEmail(clientEmail);
ownerTable = (OwnerTable) repository.findByEmail(ownerEmail);
Run Code Online (Sandbox Code Playgroud)

我的实体看起来像这样。

用户表.java

@Entity
@Table(name = "USER")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class UserTable implements Serializable {

    @Column(name = "USER_ID", nullable = false)
    private Long userId;

    @EmbeddedId
    private UserTablePK userTablePK;

    @Column(name = "PASSWORD", nullable = false, length = 512)
    private String password;

    @Column(name = "FIRSTNAME", nullable = false, length = 256)
    private String firstName;

    // get, set
}
Run Code Online (Sandbox Code Playgroud)

.. 和一个主键

用户表PK.java

@Embeddable
public class UserTablePK implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "EMAIL", nullable = false, length = 256)
    private String email;

    public UserTablePK() {
    }

    public UserTablePK(String email) {
        this.email = email;
    }

    // get, set
}
Run Code Online (Sandbox Code Playgroud)

客户端表

@Entity
@Table(name = "CLIENT")
public class ClientTable extends UserTable implements Serializable {

    @Column(name = "SHOPING_POWER")
    private Integer shoppingPower;

    @Column(name = "SHOPPING_FREQUENCY")
    private Integer shoppingFreq;
    
    // get, set
}
Run Code Online (Sandbox Code Playgroud)

所有者表

@Entity
@Table(name = "OWNER")
public class OwnerTable extends UserTable implements Serializable {

    @Column(name = "EFFICIENCY")
    private String efficiency;

    @Column(name = "SALARAY")
    private Integer;

    // get, set
}
Run Code Online (Sandbox Code Playgroud)

现在,一旦设置了实体,我就需要编写一个与上述类似的存储库,这里是我需要帮助的地方。我想写这样的东西。

UserTableRepository.java

@Repository
public interface UserTableRepository extends CrudRepository<UserTable, UserTablePK> {

    @Query("SELECT e FROM UserTable e WHERE e.userTablePK.email = ?1")
    public UserTable findByEmail(String email); // if owner email, retrieve OwnerTable; if client email, retrieve ClientTable instance

    @Query("SELECT e FROM UserTable e WHERE e.userId = ?1")
    public UserTable findByUserId(Long userId); // if owner id, retrieve OwnerTable; if client id, retrieve ClientTable instance
}
Run Code Online (Sandbox Code Playgroud)

我实际上还没有尝试过这个,因为我想检查这是否是正确的路线,但是:我很怀疑这Query是否可行。因为为了检索整个子类对象,应该使用某种 JOIN,问题是我不能明确地说 ie。JOIN ClientTable因为那样我将无法获取任何OwnerTable实体。

我怎样才能实现从同一个存储库中获取两个子类?

更新

此外,要求是能够获取特定的子类。所以像:

List<ClientTable> clients = repository.findAllClients();
Run Code Online (Sandbox Code Playgroud)

是否可以使用相同的存储库,还是应该编写特定于子类的存储库?例如。

@Repository
public interface ClientTableRepository extends CrudRepository<ClientTable, ClientTablePK> {
 // empty
}
Run Code Online (Sandbox Code Playgroud)

...然后像这样称呼它们:

ClientTableRepository repository = // ...

List<ClientTable> clients = repository.findAll();
Run Code Online (Sandbox Code Playgroud)

这是否足以让 JPA 确定如何仅查找特定子类的所有实例?

Sim*_*lli 3

您想要实现的正是 JPA 中继承的工作方式。

因此,您的查询完全没问题,并且结果列表中将包含子类的实例。

在我的一篇博客文章中了解有关 JPA 继承的更多信息:

https://72.services/inheritance-in-jpa/