Я только что добавил отношение с @CreatedBy к одному из моих энтитов, и с тех пор я получаю исключение NullPointerException, обращающееся к нему через ID. Но обо всем по порядку:
Сущность. Я оставляю некоторые поля, но оставляю «владельца» на месте, так как трассировка стека (см. Ниже) относится к этому. «Создатель» - это отношение, которое я добавил.
@Entity
@Data
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Invitation implements BaseEntity<Long>, OwnedEntity {
@Id
@GeneratedValue
private Long id;
@NotNull
@ManyToOne
private Company owner;
@CreatedBy
@OneToOne
private Account creator;
...
}
Поле «Создатель» устанавливается моей реализацией AuditorAware, которое выглядит следующим образом:
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuditorProvider implements AuditorAware<Account> {
private static final Log LOG = LogFactory.getLog(AuditorProvider.class);
private final @NonNull AccountRepo accountRepo;
@Override
public Optional<Account> getCurrentAuditor() {
Optional<Account> opt = accountRepo.findMe();
if (opt.isPresent()) {
LOG.debug("Found auditor: " + opt.get());
} else {
LOG.debug("No auditor found.");
}
return opt;
}
}
Метод accountRepo.findMe () находит текущий экземпляр Account на основе контекста безопасности.
С этим на месте, когда я отправляю объект приглашения типа
curl -XPOST -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" localhost:8081/invitations -d '{"email":"k@lo.de","role":"http://localhost:8081/roles/139"}'
, тело ответа выглядит хорошо:
{
"email" : "k@lo.de",
"_links" : {
"self" : {
"href" : "http://localhost:8081/invitations/144"
},
"invitation" : {
"href" : "http://localhost:8081/invitations/144"
},
"creator" : {
"href" : "http://localhost:8081/invitations/144/creator"
},
"role" : {
"href" : "http://localhost:8081/invitations/144/role"
},
"owner" : {
"href" : "http://localhost:8081/invitations/144/owner"
}
}
}
Таблица базы данных для приглашений и журналы показывают, что «создатель» был успешно установлен.
Выборка всех приглашений работает без ошибок:
curl -v -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" http://localhost:8081/invitations
При получении этого приглашения с идентификатором 144 возникает ошибка HTTP 500:
curl -v -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" http://localhost:8081/invitations/144
Просматривая журналы, я вижу эту трассировку стека: https://pastebin.com/mVzHHddU
Причина Я оставил отношение «владелец» в приведенном выше фрагменте этой строки:
at training.edit.identity.model.Company.hashCode(Company.java:22) ~[classes/:na]
Кроме этого, ни одна из строк мне не знакома, и я не могу понять смысл ошибки.
Любые идеи будут высоко оценены!
Редактировать: Субъект компании
@Data
@NoArgsConstructor
@Entity
public class Company implements BaseEntity<Long>, OwnedEntity {
@Id
@GeneratedValue
private Long id;
@NotNull
private String name;
@NotNull
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<Address> addresses = new HashSet<Address>();
public boolean addAddress(Address address) {
return this.addresses.add(address);
}
@JsonIgnore
@Override
public ScopedEntity getParent() {
return null;
}
@JsonIgnore
@Override
public Set<Company> getTenants() {
return Sets.newHashSet(this);
}
@Override
public void configureTenant(Company tenant) {
throw new RuntimeException("Cannot configure tenant on Company.");
}
}
Редактировать: Из-за Ниже приведен комментарий, связанный с lombok, я удалил аннотацию @Data из Company и создал методы получения и установки вручную. Таким образом, получение приглашения по идентификатору работает.
Имеет ли это смысл для кого-либо?