# API output Wert, statt ID



## OnDemand (12. Jun 2018)

Hallo zusammen,

ich bin mir nicht sicher, ob mein folgender Output so logisch ist.
Ich möchte eigentlich, dass statt der ID der entsprechende Wert aus der Datenbanktabelle ausgegeben wird. Die ID sind jeweils in einer eigenen Tabelle abgespeichert. 
Ist das so sinnvoll? Ein konsumierender Service müsste ja dann eine Resource für manufacturer erstmal lesen um zu wissen, welcher Herstellername hinter der ID 1 steckt.  Geht das nicht irgendwie etwas einfacher? (SpringBoot nutz ich)


----------



## mrBrown (12. Jun 2018)

Du kannst die entsprechenden Objekte auch direkt einbetten.
Wie sehen denn die Java-Klassen dazu aus?


----------



## OnDemand (12. Jun 2018)

Manufacturer so zb


```
/**
* The persistent class for the manufacturer database table.
*
*/
@Entity
@Table(name="manufacturer")
@NamedQuery(name="Manufacturer.findAll", query="SELECT m FROM Manufacturer m")
public class Manufacturer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="manufacturer_id")
    private int manufacturerId;

    @Column(name="manufacturer_name")
    private String manufacturerName;

    public Manufacturer() {
    }

    public int getManufacturerId() {
        return this.manufacturerId;
    }

    public void setManufacturerId(int manufacturerId) {
        this.manufacturerId = manufacturerId;
    }

    public String getManufacturerName() {
        return this.manufacturerName;
    }

    public void setManufacturerName(String manufacturerName) {
        this.manufacturerName = manufacturerName;
    }

}
```

Wie könnte ich das dann einbetten? ein Objekt rein?


----------



## mrBrown (12. Jun 2018)

Wenn du Spring Boot nutzt, nutzt du doch sicher Spring Data JPA?
Auf die NamedQuery kannst du da im wesentlichen verzichten, das wird alles deutlich bequemer über Repositorys abgedeckt.


Interessanter als diese Klasse, wäre die, die Manufacturer enthält 
Dann könnte man da mehr zu sagen


----------



## OnDemand (12. Jun 2018)

Da wo Manufacturer drin steckt ist folgende:


```
@NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p")
public class Product implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "products_id")
    private int productsId;

    @Column(name = "manufacturer_id")
    private int manufacturerId;

    @Column(name = "products_rating")
    private BigDecimal productsRating;

    @Column(name = "products_sku")
    private String productsSku;

    // bi-directional many-to-one association to ProductsAttribute
    @OneToMany(mappedBy = "product")
    private List<ProductsAttribute> productsAttributes;

    // bi-directional many-to-one association to ProductsCode
    @OneToMany(mappedBy = "product")
    private List<ProductsCode> productsCodes;

    // bi-directional one-to-one association to ProductsDescription
    @OneToOne(mappedBy = "product")
    private ProductsDescription productsDescription;

    // bi-directional many-to-one association to ProductsToCategory
    @OneToMany(mappedBy = "product")
    private List<ProductsToCategory> productsToCategories;

    public Product() {
    }

    public int getProductsId() {
        return this.productsId;
    }

    public void setProductsId(int productsId) {
        this.productsId = productsId;
    }

    public int getManufacturerId() {
        return this.manufacturerId;
    }

    public void setManufacturerId(int manufacturerId) {
        this.manufacturerId = manufacturerId;
    }

    public BigDecimal getProductsRating() {
        return this.productsRating;
    }

    public void setProductsRating(BigDecimal productsRating) {
        this.productsRating = productsRating;
    }

    public String getProductsSku() {
        return this.productsSku;
    }

    public void setProductsSku(String productsSku) {
        this.productsSku = productsSku;
    }

    public List<ProductsAttribute> getProductsAttributes() {
        return this.productsAttributes;
    }

    public void setProductsAttributes(List<ProductsAttribute> productsAttributes) {
        this.productsAttributes = productsAttributes;
    }

    public ProductsAttribute addProductsAttribute(ProductsAttribute productsAttribute) {
        getProductsAttributes().add(productsAttribute);
        productsAttribute.setProduct(this);

        return productsAttribute;
    }

    public ProductsAttribute removeProductsAttribute(ProductsAttribute productsAttribute) {
        getProductsAttributes().remove(productsAttribute);
        productsAttribute.setProduct(null);

        return productsAttribute;
    }

    public List<ProductsCode> getProductsCodes() {
        return this.productsCodes;
    }

    public void setProductsCodes(List<ProductsCode> productsCodes) {
        this.productsCodes = productsCodes;
    }

    public ProductsCode addProductsCode(ProductsCode productsCode) {
        getProductsCodes().add(productsCode);
        productsCode.setProduct(this);

        return productsCode;
    }

    public ProductsCode removeProductsCode(ProductsCode productsCode) {
        getProductsCodes().remove(productsCode);
        productsCode.setProduct(null);

        return productsCode;
    }

    public ProductsDescription getProductsDescription() {
        return this.productsDescription;
    }

    public void setProductsDescription(ProductsDescription productsDescription) {
        this.productsDescription = productsDescription;
    }

    public List<ProductsToCategory> getProductsToCategories() {
        return this.productsToCategories;
    }

    public void setProductsToCategories(List<ProductsToCategory> productsToCategories) {
        this.productsToCategories = productsToCategories;
    }

    public ProductsToCategory addProductsToCategory(ProductsToCategory productsToCategory) {
        getProductsToCategories().add(productsToCategory);
        productsToCategory.setProduct(this);

        return productsToCategory;
    }

    public ProductsToCategory removeProductsToCategory(ProductsToCategory productsToCategory) {
        getProductsToCategories().remove(productsToCategory);
        productsToCategory.setProduct(null);

        return productsToCategory;
    }}
```


----------



## mrBrown (12. Jun 2018)

Naja, dein Objekt hat ja nur einen einfachen int:

```
@Column(name = "manufacturer_id")
private int manufacturerId;
```

Da steckt nicht drin, dass das ein Fremdschlüssel ist 

Du solltest die Entitys als ganz normale Objekte designen, mit ganz normalen Beziehung zu anderen Objekten (also direkt `private Manufacturer manufacturer` statt der ID), das ganze passend für die Datenbank abzubilden übernimmt dann JPA.


----------



## OnDemand (12. Jun 2018)

Vielen Dank, 

@Column(name = "manufacturer_id")
    private Manufacturer manufacturer;

sagt mir Eclipse : 
Join column "manufacturer_manufacturer_id" cannot be resolved on table "products"

Was muss ich denn dann annontieren?


----------



## mrBrown (12. Jun 2018)

NicoDeluxe hat gesagt.:


> sagt mir Eclipse :


Eclipse halt ¯\_(ツ)_/¯



NicoDeluxe hat gesagt.:


> Was muss ich denn dann annontieren?


So wie die anderen Relationen auch, mit OneToMany, ManyToOne, etc...

In dem Fall ManyToOne (und u.U. noch weitere, da hilf ein Blick in irgendein passendes JPA-Tut, da gibt eine Menge an Möglichkeiten).

(ich würde aber auch die eigene ID immer nur `id` nennen, zu welchem Objekt die gehört ist ja klar, und dann kommt da nicht sowas wie `manufacturer_manufacturer_id` bei raus. UU kann man die ID dann auch in eine Basis-Klasse ziehen.)


----------



## OnDemand (12. Jun 2018)

Dann brauch ich aber in der manufacturer Tabelle eine Referenz auf Product oder?
Manufacturer ist aber nicht abhängig von Product


----------



## mrBrown (12. Jun 2018)

Nö, warum solltest du sie brauchen?


----------



## OnDemand (12. Jun 2018)

Meinst du so? 

@ManyToOne
private List<Manufacturer> manufacturer;


----------



## mrBrown (12. Jun 2018)

Hat ein Product denn mehrere Manufacturer?


----------



## OnDemand (12. Jun 2018)

Hab ich auch grad bemerkt 

Hm komisch, jetzt hat mir Hibernate eine Spalte manufacturer_manufacturer_id in products angelegt. 
1. warum?
2. wir kann ich das vermeiden, dass es eigenständig die Datenbank verändert?


----------



## mrBrown (12. Jun 2018)

NicoDeluxe hat gesagt.:


> Hm komisch, jetzt hat mir Hibernate eine Spalte manufacturer_manufacturer_id in products angelegt.
> 1. warum?



Vorher wird es in Product doch auf eine Spalte gegeben haben, die auf Manufacturer verweist?

Die Default-Benennung für Verweise auf andere Tabellen ist <Feldname>_<Name des ID-Felds>, erstes ist hier "manufacturer", und die ID von Manufacturer ist "manufacturer_id", ergibt eben "manufacturer_manufacturer_id"



NicoDeluxe hat gesagt.:


> 2. wir kann ich das vermeiden, dass es eigenständig die Datenbank verändert?


In deinen Properties kannst du `spring.jpa.hibernate.ddl-auto` angeben, aktuell dürfte das auf update stehen (bedeutet, das Schema wird angepasst), du kannst das auf validate setzen, dann wird nur noch überprüft, ob Klassen und Schema zueinander passen. (`spring.jpa.hibernate.ddl-auto=validate`, wenn properties, mit yaml entsprechend mit dessen Syntax)


----------



## OnDemand (12. Jun 2018)

krasser typ! danke!!
so nun nochmal zu der Doppel id. hab in product eine manufacture_id und in der product_id folgenden Code

```
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "products_id")
private int productsId;

@Column(name = "manufacturer_id")
private int manufacturerId;

@ManyToOne
private Manufacturer manufacturer;
```

wie muss die denn dann korrekt lauten?


----------



## mrBrown (12. Jun 2018)

NicoDeluxe hat gesagt.:


> wie muss die denn dann korrekt lauten?


Die objekt-eigene ID kann so blieben, das bleibt völlig dir überlassen. Üblicher wäre aber einfach `id` für die eigene ID (also in diesem Fall statt `productsId`). Alle anderen IDs würde man über Beziehungen abbilden (`manufacturerId` ist in diesem Fall ja schon durch `manufacturer` ersetzt)

Würde also zu:

```
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")//uU anpassen
private int id;

@ManyToOne
private Manufacturer manufacturer;
```


----------



## OnDemand (12. Jun 2018)

Super! Vielen Dank du hast mir wie immer super weitergeholfen!

Mein Json sieht nun wie folgt aus, irgendwas zu meckern was man verbessern könnte?


```
{
    "id": 1,
    "manufacturer": {
        "manufacturerName": "Tonrtezilla"
    },
    "productsRating": 6,
    "productsSku": "12345",
    "productsAttributes": [
        {
            "productsAttributesDescription": {
                "languageId": 1,
                "productsAttributeName": "Größe"
            },
            "productsAttributesValue": {
                "productsAttributeValue": "XXL",
                "language_id": 1
            }
        }
    ],
    "productsCodes": [
        {
            "productsEan": "zzz",
            "productsMpn": "uuuu"
        }
    ],
    "productsDescription": {
        "languageId": 1,
        "productsDescription": "lange beschreibung",
        "productsName": "testname",
        "productsSeoDescription": "seo beschreibung",
        "productsSeoKeywords": "",
        "productsSeoTitle": "",
        "productsShortDescription": "kurze beschreibung"
    },
    "productsToCategories": [
        {
            "productsCategoriesId": 1
        },
        {
            "productsCategoriesId": 2
        }
    ]
}
```

Die Kategorien werden der nächste Knaller -.-
Ein Product kann in mehreren Kategorien sein, wobei jede Kategorie unterschiedlich viele Eltern und Kinder haben kann


----------



## stg (12. Jun 2018)

NicoDeluxe hat gesagt.:


> irgendwas zu meckern was man verbessern könnte?



Du könntest - wie ich dir schon seit Ewigkeiten hier im Forum predige - einfach mal anfangen Dokumentation und/oder gescheite Bücher zu den Themen zu lesen.


----------



## OnDemand (12. Jun 2018)

und in den Büchern find ich dann Erfahrungen, ja?


----------



## mrBrown (12. Jun 2018)

NicoDeluxe hat gesagt.:


> und in den Büchern find ich dann Erfahrungen, ja?


Diese Frage z.B wäre mit so gut wie jedem JPA-Tut als Grundlage gar nicht erst aufgekommen 


Und zumindest mMn sind das Grundlagen und nicht Erfahrung, die hier fehlen, da kann man aus Büchern so einiges lernen...


----------

