Запутано в Spring Data JPA и универсальных типах - PullRequest
0 голосов
/ 04 октября 2018

Таблицы:

StudentHistory 1--->n Student
TeacherHistory 1--->n Teacher

Я пытаюсь перегруппировать поведение истории JPA, потому что они делают то же самое (например, извлекают учащихся / учителей из заданной истории).

Объектыс родовыми типами:

// Entities
public abstract class AbstractHistory <T> {}
public class StudentHistory extends AbstractHistory<Student> {}
public class TeacherHistory extends AbstractHistory<Teacher> {}

Репозитории с родовыми типами:

// repositories
public interface IHistoryRepository<T> extends CrudRepository<AbstractHistory<T>, Long> {
    public AbstractHistory<T> findFirst();
}    
public interface StudentHistoryRepository extends IHistoryRepository<Student> {}
public interface TeacherHistoryRepository extends IHistoryRepository<Teacher> {}

Хотя я мог бы сделать:

StudentHistory stuHisto = new StudentHistoryRepository().findFirst(); 

Но я получаю эту ошибку:

    // err ->  Type mismatch: cannot convert from AbstractHistory<Student> to StudentHistory

1 / Почему я не могу получить 'StudentHistory' из своего 'StudentHistoryRepository'?

2 / Как мне поступить с этим?

1 Ответ

0 голосов
/ 04 октября 2018

У вас есть эта проблема, потому что ваш метод явно возвращает AbstractHistory, а не подтип.

  1. Вам нужно будет привести ...
  2. ... если только вашРеализация репозитория понимала, что с каждым T вы получаете определенную историю.

Вы можете попробовать добавить другой тип, но я боюсь, что он потерпит неудачу:

public interface IHistoryRepository<
  T,
  H extends AbstractHistory<T>
> extends CrudRepository<H, Long> {
    public H findFirst();
}    
public interface StudentHistoryRepository extends IHistoryRepository<Student, StudentHistory> {}
public interface TeacherHistoryRepository extends IHistoryRepository<Teacher, TeacherHistory> {}

Я не знаюкакой фреймворк вы используете, вероятно Spring Data из имен;Хотя я использовал это в прошлом, я не знаю, сможет ли он это сделать.

В конце концов, ему нужно получить конкретный класс, и поскольку он является универсальным, стирание типов может помешать (если информация о конкретном типе, представляющем H, потеряна в отражении, то Spring Data, вероятно, не сможетделайте здесь много, если только вы не поможете с аннотацией или чем-то еще).

Другое решение, которое должно работать, - это сделать это для каждого дочернего интерфейса:

public interface StudentHistoryRepository extends CrudRepository<StudentHistory, Long> {
  StudentHistory findFirst();
}

Или с другим интерфейсом:

  public interface FindFirst<T> {
    T findFirst();
  }

  public interface StudentHistoryRepository extends CrudRepository<StudentHistory, Long>, FindFirst<StudentHistory> {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...