Eu tenho uma classe abstrata:
@Entity
@Table(name = "cas_base_accounts", schema = "connectors_account_service")
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@SuperBuilder
@NoArgsConstructor
public abstract class BaseAccount {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true)
private Integer id;
//some fields here
E duas subclasses:
@Entity
@Table(name = "cas_simple_auth_accounts", schema = "connectors_account_service")
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
public class SimpleAuthAccount extends BaseAccount {
@Id
@GeneratedValue
private Integer id;
@NotNull
@JsonIgnore
private String clientId;
@NotNull
@JsonIgnore
private String clientSecret;
//some other fields
E:
@Entity
@Table(name = "cas_oauth_accounts", schema = "connectors_account_service")
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
public class OAuthAccount extends BaseAccount {
@Id
@GeneratedValue
private Integer id;
@JsonIgnore
private String state;
@JsonIgnore
private LocalDateTime stateExpirationTime;
@Transient
private String tokenLink;
//some fields
Quando executei uma solicitação GET simples, http://localhost:8889/accountservice/accountIds?cabinetId=12
recebi um erro:
threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Cannot instantiate abstract class or interface: :
test.connectorsaccountservice.accountservice.model.BaseAccount; nested exception is org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: : test.connectorsaccountservice.accountservice.model.BaseAccount]
Entidades com cabinetId = 12 são sempre uma SimpleAuthAccount. Quando eu executei, por exemplo, cabinetId = 10, ele retornou o resultado correto. Neste caso, entidades com id != 12 (e 21) são OauthAccount.
Isso mostra que ocorre erro neste método:
public Mono<List<Integer>> getAccountIds(Integer cabinetId) {
return findServiceByCabinetId(cabinetId)
.then(Mono.fromCallable(() -> baseAccountRepository.findByCabinetId(cabinetId)))
.flatMapIterable(e -> e)
.filter(oAuthAccount -> !oAuthAccount.getIsDeleted()
&& UserStatus.ENABLED.equals(oAuthAccount.getUserStatus()))
.map(BaseAccount::getId)
.collectList();
}
Nesta linha:
.then(Mono.fromCallable(() -> baseAccountRepository.findByCabinetId(cabinetId)))
Repositório:
public interface BaseAccountRepository extends JpaRepository<BaseAccount, Integer> {
Optional<BaseAccount> findByIdAndCabinetId(Integer accountId, Integer cabinetId);
Optional<BaseAccount> findByCabinetIdAndAccountLogin(Integer cabinetId, String accountLogin);
List<BaseAccount> findByCabinetId(Integer cabinetId);
Repositório SimpleAuthAccount:
@Repository
public interface SimpleAuthAccountRepository extends
JpaRepository<SimpleAuthAccount, Integer>,
CustomAccountRepository<SimpleAuthAccount, Integer> {
@Query("SELECT a FROM SimpleAuthAccount a " +
"JOIN BaseCabinet c ON a.cabinetId = c.id " +
"WHERE " +
"(:realmId IS NULL OR a.realmId = :realmId) AND " +
"(:accountLogin IS NULL OR a.accountLogin = :accountLogin) AND " +
"(:accountId IS NULL OR a.id = :accountId) AND " +
"(:cabinetId IS NULL OR a.cabinetId = :cabinetId) AND " +
"(:isDeleted IS NULL OR a.isDeleted = :isDeleted) AND " +
"((:advertiserIds) IS NULL OR a.advertiserId IN (:advertiserIds)) " +
"ORDER BY c.description, a.accountLogin")
List<SimpleAuthAccount> findAccounts(
@Param("realmId") Integer realmId,
@Param("accountLogin") String accountLogin,
@Param("accountId") Integer accountId,
@Param("cabinetId") Integer cabinetId,
@Param("isDeleted") Boolean isDeleted,
@Param("advertiserIds") Set<Integer> advertiserIds
);
}
Aliás, parece que funcionava antes, mas fiz algumas alterações. Depois que esse erro aconteceu, reverti todas as alterações, mas o erro ainda ocorre. E nessas alterações não toquei em nenhuma classe deste post, apenas em outras.
Como consertar isso? E por que isso aconteceu e por que isso ainda acontece após as alterações revertidas? Acho que adicionar @DiscriminatorColumn
e @DiscriminatorValue
pode ajudar? Para mim, a coluna existente cabinetId
será boa como @DiscriminatorColumn
, mas como posso definir o valor para isso se eu tiver uma matriz de ids para SimpleAuthAccount e matrizes de ids para OAuthAccount? Eu realmente não quero adicionar outra coluna a esta tabela. Mas é claro que se não houver mais soluções aqui, eu poderia adicionar uma coluna como auth_type
e definir SIMPLE_AUTH
e OAUTH
para essas classes.
No seu banco de dados você tem registros em
cas_base_accounts
sem registros correspondentes emcas_simple_auth_accounts
oucas_oauth_accounts
.O Hibernate acha que isso significa que tais registros têm um tipo
BaseAccount
e tenta instanciar essa classe.