Spring Data JPA и магические слова
Есть нативный запрос, который при тесте не работает, не могу найти ошибку.
Базовая Entity:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
abstract class BaseModel {
@Id
@Column(name = "id")
@Getter
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
protected BaseModel() {
}
}
Entity Teacher:
@Entity
@Table(name = "teacher")
public final class Teacher extends BaseModel {
@OneToOne
@JoinColumn(name = "teacher_id")
private PupilInClassRoom pupilInClassRoom;
@Column(nullable = false)
@Getter
@Setter
private String name;
@Column(nullable = false)
@Getter
@Setter
private String surname;
@Column(nullable = false)
@Getter
@Setter
private String discipline;
public Teacher() {
}
}
Entity Pupil:
@Entity
@Table(name = "pupil")
public final class Pupil extends BaseModel {
@OneToOne
@JoinColumn(name = "pupil_iD")
private PupilInClassRoom pupilInClassRoom;
@Column(nullable = false)
@Getter
@Setter
private String name;
@Getter
@Setter
@Column(nullable = false)
private String surname;
public Pupil() {
}
}
Entity ClassRoom:
@Entity
@Table(name = "class_room")
public final class ClassRoom extends BaseModel {
@OneToOne
@JoinColumn(name = "class_Room_id")
private PupilInClassRoom pupilInClassRoom;
@Column(nullable = false)
@Getter
@Setter
private String name;
public ClassRoom() {
}
}
Entity PupilInClassRoom:
@Entity
@Table(name = "pupil_in_class_room")
public final class PupilInClassRoom extends BaseModel {
@OneToOne(mappedBy = "pupilInClassRoom")
@Getter
@Setter
private Pupil pupil;
@OneToOne(mappedBy = "pupilInClassRoom")
@Getter
@Setter
private ClassRoom classRoom;
@OneToOne(mappedBy = "pupilInClassRoom")
@Getter
@Setter
private Teacher teacher;
public PupilInClassRoom() {
}
Запрос:
public interface PupilRepository extends CrudRepository<Pupil,Long> {
List<Pupil> findByName(String name);
@Query(nativeQuery = true, value = "SELECT p.id, p.name, p.surname " +
"FROM pupil p " +
"INNER JOIN pupil_in_class_room in ON p.pupil_id = in.id " +
"INNER JOIN teacher t ON t.teacher_id = in.id " +
"WHERE t.name = :name ")
List<Pupil> findPupilByTeacher(@Param("name") String name);
}
Cуть запроса, вывести учеников по имени учителя
Тест:
@Test
@Rollback(value = false)
public void createEntity() {
Pupil pupil = new Pupil();
pupil.setName("Hello");
pupil.setSurname("hello");
Teacher teacher = new Teacher();
teacher.setName("Alla");
teacher.setSurname("Aronova");
teacher.setDiscipline("Mat");
ClassRoom classRoom = new ClassRoom();
classRoom.setName("1A");
PupilInClassRoom pupilInClassRoom = new PupilInClassRoom();
teacher.setPupilInClassRoom(pupilInClassRoom);
pupil.setPupilInClassRoom(pupilInClassRoom);
classRoom.setPupilInClassRoom(pupilInClassRoom);
pupilInClassRoomRepository.save(pupilInClassRoom);
teacherRepository.save(teacher);
pupilRepository.save(pupil);
classRoomRepository.save(classRoom);
Iterable<Pupil> allPupil = pupilRepository.findAll();
for (Pupil pupil1 : allPupil) {
System.out.println("Ученики");
System.out.println("----------------------------");
System.out.println(pupil1.getId() + " " +
pupil1.getName() + " " +
pupil1.getSurname());
System.out.println("----------------------------");
}
Iterable<Teacher> allTeacher = teacherRepository.findAll();
for (Teacher teacher1 : allTeacher) {
System.out.println("Учителя");
System.out.println("----------------------------");
System.out.println(teacher1.getId() + " " +
teacher1.getName() + " " +
teacher1.getSurname() + " " +
teacher1.getDiscipline());
System.out.println("----------------------------");
}
Iterable<ClassRoom> allClassRoom = classRoomRepository.findAll();
for (ClassRoom classRoom1 : allClassRoom) {
System.out.println("Класс");
System.out.println("----------------------------");
System.out.println(classRoom1.getId() + " "
+classRoom1.getName());
System.out.println("----------------------------");
}
Iterable<PupilInClassRoom> allPupilInClassRoom = pupilInClassRoomRepository.findAll();
for (PupilInClassRoom pupilInClassRoom1 : allPupilInClassRoom) {
System.out.println("Ученики в классе");
System.out.println("----------------------------");
System.out.println(pupilInClassRoom1.getPupil().getId() + " " +
pupilInClassRoom1.getPupil().getName() + " " +
pupilInClassRoom1.getPupil().getSurname());
System.out.println(pupilInClassRoom1.getTeacher().getId() + " " +
pupilInClassRoom1.getTeacher().getName() + " " +
pupilInClassRoom1.getTeacher().getSurname() + " " +
pupilInClassRoom1.getTeacher().getDiscipline());
System.out.println(pupilInClassRoom1.getClassRoom().getId() + " " +
pupilInClassRoom1.getClassRoom().getName());
}
System.out.println("----------------------------");
System.out.println("Поиск ученика по учителю");
System.out.println("----------------------------");
System.out.println(pupilRepository.findPupilByTeacher(pupilInClassRoom.getTeacher().getName()));
}
Результат работы теста:
Ученики
----------------------------
3 Hello hello
----------------------------
Учителя
----------------------------
2 Alla Aronova Mat
----------------------------
Класс
----------------------------
4 1A
----------------------------
Ученики в классе
----------------------------
3 Hello hello
2 Alla Aronova Mat
4 1A
java.lang.NullPointerException: Cannot invoke "com.SchoolJournal.SpringHibernate.model.Teacher.getName()" because the return value of "com.SchoolJournal.SpringHibernate.model.PupilInClassRoom.getTeacher()" is null
Новый Exception если заинъектить "name":
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object[]] to type [com.SchoolJournal.SpringHibernate.model.PupilInClassRoom] for value '{3, 1, Hello, hello}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.math.BigInteger] to type [com.SchoolJournal.SpringHibernate.model.PupilInClassRoom]
Возможно ли в данном случае отказаться от нативного @Query и использовать магические слова Spring Data?
Ответы (1 шт):
Автор решения: Saintka
→ Ссылка
Решение первого вопроса это правильные сеттеры и правильная последовательность сохранения в репозиторий при @OneToOne, как подсказал MrFylypenko
PupilInClassRoom pupilInClassRoom = new PupilInClassRoom();
teacher.setPupilInClassRoom(pupilInClassRoom);
pupil.setPupilInClassRoom(pupilInClassRoom);
classRoom.setPupilInClassRoom(pupilInClassRoom);
pupilInClassRoomRepository.save(pupilInClassRoom);
teacherRepository.save(teacher);
pupilRepository.save(pupil);
classRoomRepository.save(classRoom);
Решение второго вопроса отказаться от нативного Query используя магически слова
public interface PupilRepository extends CrudRepository<Pupil,Long> {
List<Pupil> findByName(String name);
List<Pupil> findByPupilInClassRoomTeacherName(String name);
}