Учитывая, что у меня есть 4 таблицы:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class SourceEvent {
@Id
private Long id;
}
@Entity
@PrimaryKeyJoinColumn(name = "SOURCE_EVENT_ID")
public class PrimaryEvent extends SourceEvent {
@ManyToOne
private Account account;
}
@Entity
@PrimaryKeyJoinColumn(name = "SOURCE_EVENT_ID")
public class SecondaryEvent extends SourceEvent {
@ManyToOne
private Account account;
}
@Entity
public class Account {
@Id
private Long id;
@NaturalId
@Column(name = "ACCOUNT_NUMBER", unique = true, nullable = false)
private long accountNumber;
}
Как видите, SourceEvent
является родителем PrimaryEvent
и SecondaryEvent
, и оба события указывают на Account
.
Я бы хотел отфильтровать SourceEvent
s по номеру счета Account
, используя API критериев JPA.
Я собрал это:
final class Filter {
private Long accountNumber;
Specification<SourceEvent> toSpecification() {
return (Root<SourceEvent> root, CriteriaQuery query, CriteriaBuilder cb) -> {
return cb.or(
cb.equal(cb.treat(root, PrimaryEvent.class).get("account").get("accountNumber"), accountNumber),
cb.equal(cb.treat(root, SecondaryEvent.class).get("account").get("accountNumber"), accountNumber)
);
};
}
}
, где я использую treat
оператор понижается с SourceEvent
до PrimaryEvent
и SecondaryEvent
, и я ставлю оба равных Predicate
с cb.or(...)
Когда я звоню sourceEventRepository.findAll(filter.toSpecification())
, тогда как sourceEventRepository
:
public interface SourceEventRepository extends JpaSpecificationExecutor<SourceEvent>, JpaRepository<SourceEvent, Long> {}
тогда я получаю следующий SQL, сгенерированный Hibernate:
...
from
source_event sourceeven0_
inner join
primary_event sourceeven0_1_
on sourceeven0_.id=sourceeven0_1_.source_event_id
inner join
secondary_event sourceeven0_2_
on sourceeven0_.id=sourceeven0_2_.source_event_id
cross join
account account1_
where
sourceeven0_1_.account_id=account1_.id
and (
account1_.account_number=123
or account1_.account_number=123
)
, что не работает для меня, потому что оно не включает SecondaryEvent
s с данным номером счета.
Как заставить это работать?