oracle – Jpa – Hibernate ManyToMany做很多插入连接表

前端之家收集整理的这篇文章主要介绍了oracle – Jpa – Hibernate ManyToMany做很多插入连接表前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我遵循WorkDay(具有注释ManyToMany)和Event之间的ManyToMany关系

WorkDay entity

@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;
    }
}

Event entity

@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",length = 16)
    private EventState state;

    protected Event() {
    }
}

为了清晰起见,附加的UI表单

当我第一次按下带有运行图标的Clock时,它意味着在bean中创建“创建事件并开始工作日”,调用以下方法

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表
>插入work_day_event表

在UI上更新仅附加框架.总是看起来很好..当前的WorkDay对象在events集合中有一个元素,也将所有数据都插入到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数据的新行.并且如果编辑行,则执行一次插入等操作.在结果中,我在work_day_event表中有几个等于行.为什么会这样?

link to github project repository(look ver-1.1.0-many-to-many-problem branch)

对于WokrDay实体中的事件,将CascadeType.ALL更改为CascadeType.MERGE

使用此代码

@ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.MERGE)

代替

@ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)

不要使用ArrayList,使用HashSet.因为ArrayList允许重复.

有关CasecadeType的更多信息,请按照教程:

> Hibernate JPA Cascade Types
> Cascading best practices

猜你在找的Oracle相关文章