Ich habe folgt ManyToMany
Beziehung zwischen WorkDay
(hat Anmerkung ManyToMany) und Event
JPA - Hibernate ManyToMany tun viele Insert in Join-Tabelle
WORKDAY Einheit
@Entity
@Table(name = "WORK_DAY", uniqueConstraints = { @UniqueConstraint(columnNames = { "WORKER_ID", "DAY_ID" }) })
@NamedQueries({
@NamedQuery(name = WorkDay.GET_WORK_DAYS_BY_MONTH, query = "select wt from WorkDay wt where wt.worker = :worker and to_char(wt.day.day, 'yyyyMM') = :month) order by wt.day"),
@NamedQuery(name = WorkDay.GET_WORK_DAY, query = "select wt from WorkDay wt where wt.worker = :worker and wt.day = :day") })
public class WorkDay extends SuperClass {
private static final long serialVersionUID = 1L;
public static final String GET_WORK_DAYS_BY_MONTH = "WorkTimeDAO.getWorkDaysByMonth";
public static final String GET_WORK_DAY = "WorkTimeDAO.getWorkDay";
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "WORKER_ID", nullable = false)
private Worker worker;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DAY_ID", nullable = false)
private Day day;
@Column(name = "COMING_TIME")
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime comingTime;
@Column(name = "OUT_TIME")
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime outTime;
@Enumerated(EnumType.STRING)
@Column(name = "STATE", length = 16, nullable = false)
private WorkDayState state = WorkDayState.NO_WORK;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "WORK_DAY_EVENT", joinColumns = {
@JoinColumn(name = "WORK_DAY_ID", nullable = false)}, inverseJoinColumns = {
@JoinColumn(name = "EVENT_ID", nullable = false)})
@OrderBy(value = "startTime desc")
private List<Event> events = new ArrayList<>();
protected WorkDay() {
}
public WorkDay(Worker worker, Day day) {
this.worker = worker;
this.day = day;
this.state = WorkDayState.NO_WORK;
}
}
Ereignis Einheit
@Entity
@Table(name = "EVENT")
public class Event extends SuperClass {
@Column(name = "DAY", nullable = false)
@Convert(converter = LocalDateAttributeConverter.class)
private LocalDate day;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TYPE_ID", nullable = false)
private EventType type;
@Column(name = "TITLE", nullable = false, length = 128)
private String title;
@Column(name = "DESCRIPTION", nullable = true, length = 512)
private String description;
@Column(name = "START_TIME", nullable = false)
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime startTime;
@Column(name = "END_TIME", nullable = true)
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime endTime;
@Enumerated(EnumType.STRING)
@Column(name = "STATE", nullable = false, length = 16)
private EventState state;
protected Event() {
}
}
Befestigt UI Form für Klarheit
Wenn ich Uhr mit Lauf Symbol ersten Mal drücken, bedeutet das „Ereignis erstellen und Arbeitstag starten“ in Bohne, die folgenden Methoden aufrufen:
public void startEvent() {
stopLastActiveEvent();
Event creationEvent = new Event(workDay.getDay().getDay(), selectedEventType, selectedEventType.getTitle(),
LocalDateTime.now());
String addEventMessage = workDay.addEvent(creationEvent);
if (Objects.equals(addEventMessage, "")) {
em.persist(creationEvent);
if (workDay.isNoWork()
&& !creationEvent.getType().getCategory().equals(EventCategory.NOT_INFLUENCE_ON_WORKED_TIME)) {
startWork();
}
em.merge(workDay);
} else {
Notification.warn("Невозможно создать событие", addEventMessage);
}
cleanAfterCreation();
}
public String addEvent(Event additionEvent) {
if (!additionEvent.getType().getCategory().equals(NOT_INFLUENCE_ON_WORKED_TIME)
&& isPossibleTimeBoundaryForEvent(additionEvent.getStartTime(), additionEvent.getEndTime())) {
events.add(additionEvent);
changeTimeBy(additionEvent);
} else {
return "Пересечение временых интервалов у событий";
}
Collections.sort(events, new EventComparator());
return "";
}
private void startWork() {
workDay.setComingTime(workDay.getLastWorkEvent().getStartTime());
workDay.setState(WorkDayState.WORKING);
}
In log ich sehe:
- Einsatz in Ereignistabelle
- Update work_day Tabelle
- Einsatz in work_day_event Tabelle
auf UI aktualisiert nur angebracht Rahmen. Immer sieht gut aus .. aktuelles WorkDay
Objekt hat ein Element in der events
Sammlung, auch alle Daten in DB
eingeführt werden .. aber wenn diese Zeit bearbeitet Ereignis Reihe
Ereignis Reihe Zuhörer:
public void onRowEdit(RowEditEvent event) {
Event editableEvent = (Event) event.getObject();
LocalDateTime startTime = fixDate(editableEvent.getStartTime(), editableEvent.getDay());
LocalDateTime endTime = fixDate(editableEvent.getEndTime(), editableEvent.getDay());
if (editableEvent.getState().equals(END) && startTime.isAfter(endTime)) {
Notification.warn("Невозможно сохранить изменения", "Время окончания события больше времени начала");
refreshEvent(editableEvent);
return;
}
if (workDay.isPossibleTimeBoundaryForEvent(startTime, endTime)) {
editableEvent.setStartTime(startTime);
editableEvent.setEndTime(endTime);
workDay.changeTimeBy(editableEvent);
em.merge(workDay);
em.merge(editableEvent);
} else {
refreshEvent(editableEvent);
Notification.warn("Невозможно сохранить изменения", "Пересечение временых интервалов у событий");
}
}
in die einfügen neue Zeile mit den gleichen work_day_id
und event_id
Daten. Und wenn edit row sonst noch einen einfügen und etc .. Im Ergebnis habe ich mehrere gleich Zeilen in work_day_event
Tabelle. Warum passiert das?
link to github project repository(look ver-1.1.0-many-to-many-problem branch)
Sie haben 'CascadeType.ALL' für die Ereignisse in den Arbeitstag. Das bedeutet, dass das Ereignis nicht separat gespeichert werden muss. Das Speichern des Arbeitstages sollte den Job erledigen: 'em.merge (workDay);'. –
@XtremeBiker, ja, aber es ist nicht mein Problem resoled – HAYMbl4
Haben Sie versucht, die separate Mapper-Entity-Klasse für das work_day_event verwenden? –