MySQL JPA: UNIQUE-Constraint kommt aus dem Nichts

krgewb

Top Contributor
Ich habe diese beiden Klassen.

Java:
package com.a.vision.backend.database.entities;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "VIDEO_SOURCE_CHANNEL_TESTEKE", schema = "MEDIA_SERVER", catalog = "", uniqueConstraints = {@UniqueConstraint(name = "VIDEO_SOURCE_ID", columnNames = {"VIDEO_SOURCE_ID", "VIEW_ID", "CHANNEL"})}, indexes = {@Index(columnList = "STORAGE_ID", name = "STORAGE_ID"), @Index(columnList = "VIEW_ID", name = "VIEW_CHANNEL")})
public class VideoSourceChannelEntity implements Serializable {

    @EmbeddedId
    private VideoSourceChannelEntityPK pk;

    @Column(name = "VIEW_ID", nullable = false)
    private Long viewId;

    @Column(name = "PORT", nullable = false)
    private short port;

    @Column(name = "LIVE_ONLY", nullable = false)
    private short liveOnly;

    @Column(name = "ACTIVE", nullable = false)
    private short active;

    @Column(name = "FILE_LENGTH")
    private Long fileLength;

    @Column(name = "SCHEDULE", length = 150)
    private String schedule;

    @Column(name = "TIME_TO_LIVE")
    private Long timeToLive;

    @Column(name = "TRANSPORT_PROTOCOL", length = 32, nullable = false)
    private String transportProtocol;

    @Column(name = "RTCP", nullable = false)
    private short rtcp;

    @Column(name = "CODEC", length = 30)
    private String codec;

    @Column(name = "URL_PATTERN", length = 256)
    private String urlPattern;

    @Column(name = "PRE_ALARM_LENGTH")
    private Long preAlarmLength;

    @Column(name = "POST_ALARM_LENGTH")
    private Long postAlarmLength;

    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "STORAGE_ID", referencedColumnName = "ID")
    private StorageEntity storage;

    @Column(name = "WIDTH")
    private Integer width;

    @Column(name = "HEIGHT")
    private Integer height;

    @Column(name = "PERIOD")
    private Integer period;

    @Column(name = "MAX_BITRATE")
    private Long maxBitrate;

    @Column(name = "CONSTANT")
    private short constant;

    @Column(name = "QUALITY")
    private short quality;

    @Column(name = "THERMAL", columnDefinition = "smallint default 0", nullable = false)
    private short thermal;

    @Column(name = "ANALYTICS", columnDefinition = "bigint default 0", nullable = false)
    private Long analytics;

    public VideoSourceChannelEntityPK getPk() {
        return pk;
    }

    public void setPk(VideoSourceChannelEntityPK pk) {
        this.pk = pk;
    }

    public Long getViewId() {
        return viewId;
    }

    public void setViewId(Long viewId) {
        this.viewId = viewId;
    }

    public short getPort() {
        return port;
    }

    public void setPort(short port) {
        this.port = port;
    }

    public short getLiveOnly() {
        return liveOnly;
    }

    public void setLiveOnly(short liveOnly) {
        this.liveOnly = liveOnly;
    }

    public short getActive() {
        return active;
    }

    public void setActive(short active) {
        this.active = active;
    }

    public Long getFileLength() {
        return fileLength;
    }

    public void setFileLength(Long fileLength) {
        this.fileLength = fileLength;
    }

    public String getSchedule() {
        return schedule;
    }

    public void setSchedule(String schedule) {
        this.schedule = schedule;
    }

    public Long getTimeToLive() {
        return timeToLive;
    }

    public void setTimeToLive(Long timeToLive) {
        this.timeToLive = timeToLive;
    }

    public String getTransportProtocol() {
        return transportProtocol;
    }

    public void setTransportProtocol(String transportProtocol) {
        this.transportProtocol = transportProtocol;
    }

    public short getRtcp() {
        return rtcp;
    }

    public void setRtcp(short rtcp) {
        this.rtcp = rtcp;
    }

    public String getCodec() {
        return codec;
    }

    public void setCodec(String codec) {
        this.codec = codec;
    }

    public String getUrlPattern() {
        return urlPattern;
    }

    public void setUrlPattern(String urlPattern) {
        this.urlPattern = urlPattern;
    }

    public Long getPreAlarmLength() {
        return preAlarmLength;
    }

    public void setPreAlarmLength(Long preAlarmLength) {
        this.preAlarmLength = preAlarmLength;
    }

    public Long getPostAlarmLength() {
        return postAlarmLength;
    }

    public void setPostAlarmLength(Long postAlarmLength) {
        this.postAlarmLength = postAlarmLength;
    }

    public StorageEntity getStorage() {
        return storage;
    }

    public void setStorage(StorageEntity storage) {
        this.storage = storage;
    }

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public Integer getPeriod() {
        return period;
    }

    public void setPeriod(Integer period) {
        this.period = period;
    }

    public Long getMaxBitrate() {
        return maxBitrate;
    }

    public void setMaxBitrate(Long maxBitrate) {
        this.maxBitrate = maxBitrate;
    }

    public short getConstant() {
        return constant;
    }

    public void setConstant(short constant) {
        this.constant = constant;
    }

    public short getQuality() {
        return quality;
    }

    public void setQuality(short quality) {
        this.quality = quality;
    }

    public short getThermal() {
        return thermal;
    }

    public void setThermal(short thermal) {
        this.thermal = thermal;
    }

    public Long getAnalytics() {
        return analytics;
    }

    public void setAnalytics(Long analytics) {
        this.analytics = analytics;
    }
}

Java:
package com.a.vision.backend.database.entities;

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import javax.persistence.*;
import java.io.Serializable;

public class VideoSourceChannelEntityPK implements Serializable {

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "VIDEO_SOURCE_ID", referencedColumnName = "ID")
    private VideoSourceEntity videoSource;

    @Column(name = "CHANNEL")
    private short channel;

    public VideoSourceEntity getVideoSource() {
        return videoSource;
    }

    public void setVideoSource(VideoSourceEntity videoSource) {
        this.videoSource = videoSource;
    }

    public short getChannel() {
        return channel;
    }

    public void setChannel(short channel) {
        this.channel = channel;
    }
}

Die Tabelle wird von JPA erfolgreich erstellt. Es wird aber zu viel erstellt. Zusätzlich zu dem Dreier-Unique-Constraint wird ein Unique-Constraint auf VIEW_ID erstellt. Ich weißt nicht, wieso er erstellt wird.
 
Hier noch die CamEntityPK.

Java:
package com.a.vision.backend.database.entities.ng.camera;

import com.a.vision.backend.database.entities.VideoSourceChannelEntity;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;

public class CamEntityPK implements Serializable {

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "ID", referencedColumnName = "VIEW_ID")
    private VideoSourceChannelEntity videoSourceChannel;

    public VideoSourceChannelEntity getVideoSourceChannel() {
        return videoSourceChannel;
    }

    public void setVideoSourceChannel(VideoSourceChannelEntity videoSourceChannel) {
        this.videoSourceChannel = videoSourceChannel;
    }
}
 
Also, du sagst in CamEntityPK, dass dort auf genau eine VideoSourceChannelEntity verwiesen wird und dafür die View_id als Target genommen werden soll. Dafür muss die View_Id natürlich Unique sein, weil wenn die nicht unique ist, ist es kein ManyToOne mehr sondern offensichtlich ein ManyToMany. In der Regel verweist man ja auch immer auf den Primary Key.
 
Vielleicht als plastisches Beispiel:

Entity A: VideoSourceChannelEntity, VIEW_ID = 1
Entity B: VideoSourceChannelEntity, VIEW_ID = 1
Entity C: CamEntityPK mit ID = 1

Was soll nun in dem Attribut VideoSourceChannelEntity videoSourceChannel der Entity C drinstehen? Entity A? Oder Entity B?
 

Zurück
Oben