1

i have a mapping problem with spring data jdbc as following:
Student entity:

@Value(staticConstructor = "of")
public class Student {

private final @Id
@Wither
long studentId;

@NotNull
@Size(min = 4, max = 20)
private String userId;

@NotNull
@Min(0)
private int matriculationNumber;

@NotNull
@Email
private String eMail;

private @Wither
Set<StudentSubjectRegistration> studentSubjectRegistrations;
}

Next i have a StudentSubjectRegistration entity:

@Value(staticConstructor = "of")
public class StudentSubjectRegistration {

@NotNull
private String electiveType;

@NotNull
private LocalDateTime created;

@NotNull
private long subjectid;
}

When i run a test to find one specific student as illustrated here:

@Test
public void findOneStudent() throws InterruptedException, ExecutionException {
    long studentId = 2L;
    Future<Student> student = studentService.findById(2L);
    while (!student.isDone()) {
        Thread.sleep(100);
    }
    assertThat(student.get()).isNotNull();
    assertThat(student.get().getStudentId()).isEqualTo(studentId);
}

The console says that there is one sql statement issued: Executing prepared SQL statement [SELECT student.studentid AS studentid, student.userid AS userid, student.matriculationnumber AS matriculationnumber, student.email AS email FROM student WHERE student.studentid = ?]

As for my understanding there should another sql statement be issued to fetch the associated registrations, shouldn´t it?

Instead there is an exception happening: java.lang.IllegalStateException: Required identifier property not found for class de.thd.awp.student.StudentSubjectRegistration!

Do i have to model the StudentSubjectRegistration with an @Id?

StudentSubjectRegistration should not be an aggregate root. It should be a reference from Student where its registrations are saved.

Am i missing something?

Please note furthermore my trying to model entity immutability inspired by this blog post https://spring.io/blog/2018/09/27/what-s-new-in-spring-data-lovelace ...

Am i doing things right?

Thanks for your help!

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Thomas Lang
  • 1,285
  • 17
  • 35

1 Answers1

0

Entities inside an aggregate need what one might call an effective-id which must be unique in the aggregate.

In the case of List and Map these get build by a backreference to the aggregate root and the index/key of the List/Map.

With a Set there is no key, index or similar, therefore, an attribute annotated with @Id is necessary.

In your case, subjectid sounds like a promising candidate assuming a Student can't register for the same subject twice.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • Thank you Jens for your help. I have done the following: `private final @Id long subjectid;` in my `StudentSubjectRegistration` ... Now the console says: `Caused by: org.postgresql.util.PSQLException: Der Spaltenname studentSubjectRegistrations_subjectid wurde in diesem ResultSet nicht gefunden.` ... is my naming incorrect? – Thomas Lang Feb 28 '19 at 08:06
  • This is a variant of this bug: https://jira.spring.io/projects/DATAJDBC/issues/DATAJDBC-127 which among other things breaks immutable support. So you currently can't have a Set as constructor argument. – Jens Schauder Feb 28 '19 at 08:44
  • 1
    Thank you. I did the following trick to bypass this issue: `@Setter private Set studentSubjectRegistrations;` within the `Student` enttiy. – Thomas Lang Feb 28 '19 at 08:51
  • @ThomasLang An even better version is to use `@Wither` since it keeps the immutability. You'll need two constructors: One with all args. And one with the non-entity ones annotated with `@PersistenceContext`. – Jens Schauder Mar 05 '19 at 10:14