Декларация вашей сущности Relationship
предполагает использование составного первичного ключа . Итак, вы должны исправить свою сущность следующим образом:
@Table(name = "RELATIONSHIP")
@Getter
@Setter
@Entity
@ToString
@EqualsAndHashCode
@IdClass(RelationshipPK.class)
public class Relationship implements Serializable {
@Id
private Long userIdFrom;
@Id
private Long userIdTo;
@Enumerated(EnumType.STRING)
private RelationshipStatus status;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-DD HH:mm:ss")
private LocalDate friendsRequestDate;
}
, а затем RelationshipPK
:
public class RelationshipPK implements Serializable {
private Long userIdFrom;
private Long userIdTo;
public RelationshipPK(Long userIdFrom, Long userIdTo) {
this.userIdFrom = userIdFrom;
this.userIdTo = userIdTo;
}
public RelationshipPK() {
}
//Getters and setters are omitted for brevity
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
RelationshipPK pk = (RelationshipPK) o;
return Objects.equals( userIdFrom, pk.userIdFrom ) &&
Objects.equals( userIdTo, pk.userIdTo );
}
@Override
public int hashCode() {
return Objects.hash( userIdFrom, userIdTo );
}
}
, и ваш CrudRepository
должен иметь следующий вид:
public interface RelationshipRepository extends CrudRepository<Relationship, RelationshipPK>
{
@Query(value = "some query", nativeQuery = true)
Long findAmountOfFriends(@Param("userId") Long userId);
...other methods
}
На самом деле, Hibernate позволяет объявлять составной ключ и без этого. Это так называемые составные идентификаторы с ассоциациями . Но это необходимо для следующих CrudRepository методов:
public interface CrudRepository<T,ID> extends Repository<T,ID>
{
void deleteById(ID id);
boolean existsById(ID id);
Iterable<T> findAllById(Iterable<ID> ids);
Optional<T> findById(ID id);
// ...
}