новых здесь. Я новичок в Spring и Thymeleaf, я пытаюсь научиться, следя за видео, и я не знаю, почему я получаю следующее исключение (org.hibernate.TransientPropertyValueException: объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед flushing: org.launchcode.codingevents.models.Event.eventCategory -> org.launchcode.codingevents.models.EventCategory), когда я пытаюсь создать событие, присвоив ему EventCategory в форме Thymeleaf. Я пробовал каскадировать с одной стороны, затем с другой, а затем с обеих, но это не сработало.
Я буду безмерно благодарен всем, кто мне поможет.
Вот мой код .
@MappedSuperclass
public abstract class AbstractEntity {
@Id
@GeneratedValue
private int id;
public int getId() {
return id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
AbstractEntity entity = (AbstractEntity) obj;
return this.id == entity.id;
}
@Entity
public class Event extends AbstractEntity {
@NotBlank(message = "Name is required")
@Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
private String name;
@Size(max = 500, message = "Description too long!")
private String description;
@NotBlank(message = "Email is required")
@Email(message = "Invalid email. Try again")
private String contactEmail;
@ManyToOne
@NotNull(message = "Category is required")
private EventCategory eventCategory;
public Event() {
}
public Event(String name, String description, String contactEmail, EventCategory eventCategory) {
this.name = name;
this.description = description;
this.contactEmail = contactEmail;
this.eventCategory = eventCategory;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getContactEmail() {
return contactEmail;
}
public void setContactEmail(String contactEmail) {
this.contactEmail = contactEmail;
}
public EventCategory getEventCategory() {
return eventCategory;
}
public void setEventCategory(EventCategory eventCategory) {
this.eventCategory = eventCategory;
}
@Override
public String toString() {
return name;
}
@Entity
public class EventCategory extends AbstractEntity implements Serializable {
@Size(min = 3, message = "Name must be at least 3 characters long")
private String name;
@OneToMany(mappedBy = "eventCategory")
private final List<Event> events = new ArrayList<>();
public EventCategory() {
}
public EventCategory(@Size(min = 3, message = "Name must be at least 3 characters long") String name) {
this.name = name;
}
public List<Event> getEvents() {
return events;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
@Controller
@RequestMapping("events")
public class EventController {
@Autowired
private EventRepository eventRepository;
@Autowired
private EventCategoryRepository eventCategoryRepository;
@GetMapping
public String displayAllEvents(@RequestParam(required = false) Integer categoryId, Model model) {
if (categoryId == null) {
model.addAttribute("title", "All Events");
model.addAttribute("events", eventRepository.findAll());
} else {
Optional<EventCategory> result = eventCategoryRepository.findById(categoryId);
if (!result.isPresent()) {
model.addAttribute("title", "Invalid Category Id: " + categoryId);
} else {
EventCategory category = result.get();
model.addAttribute("title", "Events in Category: " + category.getName());
model.addAttribute("events", category.getEvents());
}
}
return "events/index";
}
// Lives at /events/create
@GetMapping("create")
public String displayCreateEventForm(Model model) {
model.addAttribute("title", "Create Event");
model.addAttribute(new Event());
model.addAttribute("categories", eventCategoryRepository.findAll());
return "events/create";
}
// lives at /events/create
@PostMapping("create")
public String processCreateEventForm(@Valid @ModelAttribute("newEvent") Event newEvent, Errors errors, Model model) {
if (errors.hasErrors()) {
model.addAttribute("title", "Create Event");
return "events/create";
}
model.addAttribute("events", eventRepository.findAll());
eventRepository.save(newEvent);
return "redirect:";
}
// lives at /events/delete
@GetMapping("delete")
public String displayDeleteEventForm(Model model) {
model.addAttribute("title", "Delete Events");
model.addAttribute("events", eventRepository.findAll());
return "events/delete";
}
// lives at /events/delete
@PostMapping("delete")
public String processDeleteEventForm(@RequestParam(required = false) int[] eventIds) {
if (eventIds != null) {
for (int id : eventIds) {
eventRepository.deleteById(id);
}
}
return "redirect:";
}
}
Создать событие
<nav th:replace="fragments :: navigation"></nav>
<form method="post" th:action="@{/events/create}" th:object="${event}">
<div class="form-group">
<label>Name
<input class="form-control" th:field="${event.name}">
</label>
<p class="error" th:errors="${event.name}"></p>
</div>
<div class="form-group">
<label>Description
<input class="form-control" th:field="${event.description}">
</label>
<p class="error" th:errors="${event.description}"></p>
</div>
<div class="form-group">
<label>Contact Email
<input class="form-control" th:field="${event.contactEmail}">
</label>
<p class="error" th:errors="${event.contactEmail}"></p>
</div>
<div class="form-group">
<label>Category
<select th:field="${event.eventCategory}">
<option th:each="eventCategory : ${categories}" th:value="${eventCategory.id}"
th:text="${eventCategory.name}">
</option>
</select>
<p class="error" th:errors="${event.eventCategory}"></p>
</label>
</div>
<div th:replace="fragments :: create-button"></div>
</form>