Hibernate One-To-One mit Where Klausel

jimb0p

Mitglied
Hallo Zusammen,

ich habe folgende Entities:
TartikelEntity:
Java:
package entities.artikel;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.List;
import java.util.Objects;

@Entity
@Table(name = "tartikel", schema = "dbo", catalog = "Mandant_Coding")
public class TartikelEntity {
    private long kArtikel;
    private String cArtNr;
    private List<TattributEntity> attributes;
    private List<TArtikelMerkmalEntity> merkmale;

    @Id
    @Column(name = "kArtikel")
    public long getkArtikel() {
        return kArtikel;
    }

    public void setkArtikel(long kArtikel) {
        this.kArtikel = kArtikel;
    }

    @Basic
    @Column(name = "cArtNr")
    public String getcArtNr() {
        return cArtNr;
    }

    public void setcArtNr(String cArtNr) {
        this.cArtNr = cArtNr;
    }

    @OneToMany
    @JoinColumn(name = "kArtikel")
    public List<TattributEntity> getAttributes() {
        return attributes;
    }

    public void setAttributes(List<TattributEntity> attributes) {
        this.attributes = attributes;
    }

    @OneToMany
    @JoinColumn(name = "kArtikel")
    public List<TArtikelMerkmalEntity> getMerkmale() {
        return merkmale;
    }

    public void setMerkmale(List<TArtikelMerkmalEntity> merkmale) {
        this.merkmale = merkmale;
    }
}

TattributEntity:
Java:
package entities.artikel;

import entities.TstringEntity;

import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = "tattribut", schema = "dbo", catalog = "Mandant_Coding")
public class TattributEntity {
    private long kAttribut;
    private TstringEntity value;

    @Id
    @Column(name = "kAttribut")
    public long getkAttribut() {
        return kAttribut;
    }

    public void setkAttribut(long kAttribut) {
        this.kAttribut = kAttribut;
    }

    @OneToOne
    @JoinColumn(name = "kString", insertable = false, updatable = false)
    public TstringEntity getValue() {
        return value;
    }

    public void setValue(TstringEntity value) {
        this.value = value;
    }


}

TArtikelMerkmalEntity:
Java:
package entities.artikel;

import org.hibernate.annotations.Where;

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

@Entity
@Table(name = "tArtikelMerkmal", schema = "dbo", catalog = "Mandant_Coding")
public class TArtikelMerkmalEntity implements Serializable{
    private Integer kMerkmal;
    private Integer kMerkmalWert;
    private Integer kArtikel;
    private TMerkmalWertSpracheEntity value;
    private TMerkmalEntity merkmal;

    @Id
    @Column(name = "kMerkmal")
    public Integer getkMerkmal() {
        return kMerkmal;
    }

    public void setkMerkmal(Integer kMerkmal) {
        this.kMerkmal = kMerkmal;
    }

    @Id
    @Column(name = "kMerkmalWert")
    public Integer getkMerkmalWert() {
        return kMerkmalWert;
    }

    public void setkMerkmalWert(Integer kMerkmalWert) {
        this.kMerkmalWert = kMerkmalWert;
    }

    @Id
    @Column(name = "kArtikel")
    public Integer getkArtikel() {
        return kArtikel;
    }

    public void setkArtikel(Integer kArtikel) {
        this.kArtikel = kArtikel;
    }

    @OneToOne
    @JoinColumn(name="kMerkmalWert", referencedColumnName = "kMerkmalWert")
    @Where(clause = "kSprache = 1")
    public TMerkmalWertSpracheEntity getValue() {
        return value;
    }

    public void setValue(TMerkmalWertSpracheEntity value) {
        this.value = value;
    }

    @OneToOne
    @JoinColumn(name="kMerkmal", referencedColumnName = "kMerkmal", insertable = false, updatable = false)
    public TMerkmalEntity getMerkmal() {
        return merkmal;
    }

    public void setMerkmal(TMerkmalEntity merkmal) {
        this.merkmal = merkmal;
    }
}

TMerkmalEntity:
Java:
package entities.artikel;

import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = "tMerkmal", schema = "dbo", catalog = "Mandant_Coding")
public class TMerkmalEntity {
    private int kMerkmal;
    private Integer nSort;
    private String cName;

    @Id
    @Column(name = "kMerkmal")
    public int getkMerkmal() {
        return kMerkmal;
    }

    public void setkMerkmal(int kMerkmal) {
        this.kMerkmal = kMerkmal;
    }

    @Basic
    @Column(name = "nSort")
    public Integer getnSort() {
        return nSort;
    }

    public void setnSort(Integer nSort) {
        this.nSort = nSort;
    }

    @Basic
    @Column(name = "cName")
    public String getcName() {
        return cName;
    }

    public void setcName(String cName) {
        this.cName = cName;
    }
}
und hier die die Entität die mir Probleme bereitet TMerkmalWertSpracheEntity:
Java:
package entities.artikel;

import org.hibernate.annotations.NaturalId;

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

@Entity
@Table(name = "tMerkmalWertSprache", schema = "dbo", catalog = "Mandant_Coding")
public class TMerkmalWertSpracheEntity implements Serializable{

    @Id
    private int kMerkmalWert;
    @NaturalId
    private int kSprache;

    @Column(name = "kMerkmalWert")
    public int getkMerkmalWert() {
        return kMerkmalWert;
    }

    public void setkMerkmalWert(int kMerkmalWert) {
        this.kMerkmalWert = kMerkmalWert;
    }

    @Column(name = "kSprache")
    public int getkSprache() {
        return kSprache;
    }

    public void setkSprache(int kSprache) {
        this.kSprache = kSprache;
    }
}

Ich habe alles soweit wie möglich gekürzt um es einigermaßen übersichtlich zu halten. Nun zu meinem Problem: Ich erhalte alle Daten soweit korrekt, jedoch erhalte ich die Merkmale aus tMerkmalWertSprache doppelt. Das liegt wohl daran dass in der Tabelle die Daten einmal in deutsch und in englisch hinterlegt sind, jedoch beides mal der Wert auf deutsch ist (schlecht gepflegte Datenbank). Daher habe ich die Where-Klausel eingebaut:

Java:
@Where(clause = "kSprache = 1")

Leider bringt sie absolut keine Veränderung und ich verstehe auch nicht wie bei der One-To-One Relation überhaupt mehrere Werte ausgegeben werden können. Die Tabelle tArtikelMerkmal enthält halt auch keinen Primärschlüssel sondern ist lediglich eine Mappingtabelle. Ich kann die doppelten Informationen im Code einfach löschen allerdings möchte ich verstehen, warum ich sie doppelt erhalte und wie ich es umgehen kann.

Falls noch was fehlt bitte Bescheid geben. Beste Grüße!
 
Hast du Deutsch nun Doppelt in der DB oder nicht? Hibernate kann keine selektiven Relationen - du bekommst alles zu einem FK oder garnix. Das ist bei einem ordentlichen Datenbank-Design und gut gepflegten Daten auch absolut garkein Problem.

Du kannst es umgehen, indem du die Relation nicht an der Entity abbildest sondern über eine Repository-Methode mit eigenem Query. Ziemlich hacky; aber gegen schlechten Datenbestand hilft nur das.
 
Wie soll eine Referenz-Variable (value in TArtikelMerkmalEntity) denn auf zwei Werte gleichzeitig zeigen?
Hibernate und JPA mal ganz außen vorgelassen.... also was meinst du mit deiner Frage überhaupt?

btw.: Überdenk doch mal deine NamingConventions ... das liest sich grauenvoll 😕
 
Hi Leute, danke für die Antworten. Ja die Datenbank (sowohl Aufbau als auch Benennung) ist katastrophal, allerdings habe ich da keinen Einfluss drauf, da sie von einem Unternehmen kommt. Genau Deutsch ist quasi doppelt in der Datenbank, als englisches Attribut. (Fragt nicht 😀)
 
Genau Deutsch ist quasi doppelt in der Datenbank, als englisches Attribut. (Fragt nicht 😀)

Dann solltet ihr da ansetzen. Es gibt unter Menschen, die tagtäglich mit Computern arbeiten, so ein Sprichwort: Wenn man keinen Scheiss rein tut, kommt auch kein Scheiss raus. Ihr habt Scheiss im System (falsche Daten); das Ergebnis kann also auch nicht stimmen. Dieses Problem im Code zu lösen wird euch später (vielleicht in ein paar Monaten, vielleicht in ein paar Jahren) sehr, sehr teuer zu stehen kommen.
 
Genau weil das System so kacke ist, sitze ich gerade daran und muss die Daten exportieren. Dabei muss im selben Zuge aufgeräumt werden beim Exportieren.
 
Du hast immer noch diese Frage ignoriert:
Wie soll eine Referenz-Variable (value in TArtikelMerkmalEntity) denn auf zwei Werte gleichzeitig zeigen?
Hibernate und JPA mal ganz außen vorgelassen.... also was meinst du mit deiner Frage überhaupt?



Kannst du die Daten auf Datenbank-Ebene vorverarbeiten, zB mit Liquibase die fehlerhaften Werte berichtigen?
 

Zurück
Oben