Jpa - Hibernate ManyToMany 많은 사람들이 조인 테이블에 삽입합니다.
나는 다음을 가지고 있습니다.ManyToMany
사이의 관계WorkDay
( 주석 ManyToMany가 있음) 및Event
워크데이엔티
@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;
}
}
이벤트실체
@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() {
}
}
명확화를 위한 UI 양식 첨부
Clock with run 아이콘을 처음 누르면 빈에서 "이벤트 생성 및 업무 시작"을 의미하며 다음 메서드를 호출합니다.
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);
}
로그인 정보 보기:
- 이벤트 테이블에 삽입
- 업데이트 work_day table
- work_day_event 테이블에 삽입
UI에서 첨부된 프레임만 업데이트했습니다.항상 괜찮아보이네요..현재의WorkDay
객체는 하나의 요소를 가지고 있습니다.events
collection, 또한 모든 데이터가 에 삽입됩니다.DB
.. 그러나 이번에 이벤트 행을 편집하는 경우
이벤트 행 수신기:
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("Невозможно сохранить изменения", "Пересечение временых интервалов у событий");
}
}
에게work_day_event
새 행을 같은 행에 삽입work_day_id
그리고.event_id
data. 그리고 edit row가 다른 경우에 삽입 등을 한번 더 합니다.결과적으로 나는 몇개의 같은 행을 가지고 있습니다.work_day_event
테이블. 왜 이런 일이 일어날까요?
github 프로젝트 저장소 링크(ver-1.1.0-many-to-many-problem 분기 보기)
바꾸다CascadeType.ALL
로.CascadeType.MERGE
위해서events
에서WorkDay entity
이 코드 사용
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
대신에
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
사용하지않음ArrayList
,사용하다HashSet
.왜냐면ArrayList
중복을 허용합니다.
Casecade에 대한 자세한 정보자습서를 따라 입력합니다.
간단한 해결책은 많은 관계에서 캐스케이드를 제거하고 수동으로 일을 하는 것이라고 생각합니다!어쨌든 이미 중복해서 하시는 것을 봅니다.CascadeType을 제거해 보십시오.ALL
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@ManyToMany 관계를 유지하는 방법 - 중복 항목 또는 분리된 엔티티
언급URL : https://stackoverflow.com/questions/36812689/jpa-hibernate-manytomany-do-many-insert-into-join-table
'source' 카테고리의 다른 글
표현식을 사용한 Oracle 고유 제약 조건 (0) | 2023.10.21 |
---|---|
숫자에서 MySQL MOONTHNAME() (0) | 2023.10.16 |
*nix 의사단말기는 어떻게 작동합니까?마스터/슬레이브 채널은 무엇입니까? (0) | 2023.10.16 |
CSS 필터: 투명도가 있는 컬러 이미지를 흰색으로 만듭니다. (0) | 2023.10.16 |
(함수명)의 크기'는 무엇을 반환합니까? (0) | 2023.10.16 |