【问题标题】:Spring Data Repository with Inheritance.JOINED带有 Inheritance.JOINED 的 Spring 数据存储库
【发布时间】:2018-07-19 22:49:29
【问题描述】:

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

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

我想要实现的目标是拥有一个单一的存储库,我可以在其中通过IdEmailUserTableClientTableOwnerTable)。重要的要求是,一旦它们被提取,它们就可以转换为正确的类型,并且它们带有特定的字段(而不仅仅是从 UserTable 继承的字段)。

同样重要的是,我应该能够通过同一个存储库持久化这些实体,即。 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);

我的实体看起来像这样。

UserTable.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
}

.. 和一个主键

UserTablePK.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
}

ClientTable.java

@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
}

OwnerTable.java

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

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

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

    // get, set
}

现在,一旦设置了实体,我就需要编写一个像上面描述的那样运行的存储库,这就是我需要帮助的地方。我想写这样的东西。

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
}

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

如何实现从同一个存储库中获取两个子类?

更新

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

List<ClientTable> clients = repository.findAllClients();

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

@Repository
public interface ClientTableRepository extends CrudRepository<ClientTable, ClientTablePK> {
 // empty
}

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

ClientTableRepository repository = // ...

List<ClientTable> clients = repository.findAll();

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

【问题讨论】:

  • 我应该使用类似“SELECT e FROM UserTable JOIN ClientTable JOIN OwnerTable e WHERE e.userTablePK.email = ?1”吗?那么首先加入所有表,然后对加入的所有表执行 SELECT 操作?

标签: java spring hibernate jpa inheritance


【解决方案1】:

您想要实现的正是 JPA 中继承的工作原理。

所以您的查询非常好,您将在结果列表中拥有子类的实例。

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

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

【讨论】:

  • 嗯,但是像“SELECT e FROM UserTable e WHERE e.userTablePK.email = ?1”这样的查询不会加入来自“OwnerTable”和“ClientTable”的列,对吗?那么这将如何获取子类特定字段呢?
  • 这一切都由 JPA 完成。您不必关心查询!
  • 您是说 JPA 会自动将我的显式查询(参见“@Query”注释)转换为使用 JOIN 的其他查询吗?而且我需要使用这样的显式查询,因为我使用的是嵌入式 PK(通过电子邮件获取)。如果是这样,那么一切都很好。你确定吗?
  • 是的!请在询问之前尝试您的代码并打开 SQL 日志记录,您将看到 SQL 语句
猜你喜欢
  • 2010-12-06
  • 2016-03-26
  • 2021-07-12
  • 2017-08-30
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
相关资源
最近更新 更多