Следуя прекрасным советам, данным в этом посте ...
Как смоделировать трехсторонние отношения в микро-сервисе JPA Spring Boot с серверной частью MySQL
.. Я кодировал три класса Entity (показанных ниже) в Java-приложении Spring-boot, чтобы представить базу навыков моей организации, где у каждого пользователя может быть много навыков. Атрибут enum уровня используется для представления компетенции пользователя для каждого конкретного навыка.
Я добавил несколько сопоставлений контроллеров, запустил свое приложение и провел базовое тестирование API, в котором я смог успешно добавить навыки пользователям и указать дополнительный атрибут уровня.
Вот классы сущностей:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Integer id;
private String name;
private String email;
@OneToMany(mappedBy = "user",
cascade = CascadeType.MERGE,
orphanRemoval = true
)
private Set<UserSkill> skills = new HashSet<>();
(getters and setters)
@Entity
@Table(name = "skills")
public class Skill {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Integer id;
private String name;
@OneToMany(mappedBy = "skill",
cascade = CascadeType.MERGE,
orphanRemoval = true
)
private Set<UserSkill> users = new HashSet<>();
(getters and setters)
@Entity
@Table(name = "users_skills")
public class UserSkill {
@EmbeddedId
private UserSkillId id;
@ManyToOne
@JoinColumn(name = "fk_user", insertable = false, updatable = false)
private User user;
@ManyToOne
@JoinColumn(name = "fk_skill", insertable = false, updatable = false)
private Skill skill;
@Column
@Enumerated(EnumType.STRING)
private Level level;
public UserSkill() {
}
public UserSkill(User u, Skill s, Level l) {
// create primary key
this.id = new UserSkillId(u.getId(), s.getId());
// initialize attributes
this.user = u;
this.skill = s;
this.level = l;
// update relationships to assure referential integrity
u.getSkills().add(this);
s.getUsers().add(this);
}
Я назначаю навыки пользователям, использующим классы репозитория, представляющие три сущности:
User user = userRepository.findById(userid).get();
Skill skill= skillRepository.findById(skillid).get();
Level level = Level.valueOf(levelid);
UserSkill userSkill = new UserSkill(user, skill, level);
userSkillRepository.save(userSkill);
In my Controller, I have a mapping to retrieve the user and associated skills and add this to my Model:
@GetMapping("/user/{userid}/skills/get")
public String getUserSkills(@PathVariable("userid") Integer userid, Model model) {
User user = userRepository.findById(userid).get();
model.addAttribute("user", user);
Set<UserSkill> userSkills = userSkillRepository.findAllByUser(user);
model.addAttribute("userskills", userSkills);
return "update-user";
}
На мой взгляд (HTML и ThymeLeaf) я пытаюсь отобразить эту информацию.
Когда у пользователя нет навыков, я могу успешно отобразить пользователя в своем представлении. Но когда у пользователя есть навыки, и я пытаюсь получить навыки, как это ...
<tr th:each="userskill : ${userskills}">
<td th:text="${userskill.skill.name}"></td>
... Я получаю следующую ошибку:
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'skill' cannot be found on object of type 'uk.gov.hmrc.skills.model.UserSkill' - maybe not public or not valid?
Я предположил, что это потому, что в моем классе UserSkill Entity не было геттеров и сеттеров, поэтому я добавил их. Но это сделало меня шаг назад. Теперь, когда я пытаюсь добавить навык для пользователя, как этот ...
userSkillRepository.save(userSkill);
... Я вхожу в бесконечный цикл.
В необработанном выводе я вижу, что это повторяется, казалось бы, бесконечно:
{"id":1,"name":"Dave","email":"dave@test.com","skills":[{"user":
{"id":1,"name":"Dave","email":"dave@test.com","skills":[{"user":
{"id":1,"name":"Dave","email":"dave@test.com","skills":[{"user":
...
Этого не происходит, когда геттеры и сеттеры не входят в мой класс UserSkill Entity.
Как относительный новичок в JPA, я растерялся и растерялся на этом этапе и был бы очень признателен за помощь и руководство!