【发布时间】:2018-07-19 22:49:29
【问题描述】:
我在我的应用程序中设计了实体以遵循 Hibernate 的继承策略Inheritance.JOINED。
基础抽象类是UserTable,具体派生类是ClientTable和OwnerTable。
我想要实现的目标是拥有一个单一的存储库,我可以在其中通过Id 或Email 来UserTable(ClientTable 和OwnerTable)。重要的要求是,一旦它们被提取,它们就可以转换为正确的类型,并且它们带有特定的字段(而不仅仅是从 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