# JPA->fehler beim Insert in die Datenbank



## bizkit (21. Mrz 2016)

Hallo, ich habe seit kurzem mit JavaEE bzw JPA angefangen und kenne mich nicht so gut aus.
Deshalb richte ich mich wegen einem Fehler an Euch.

Folgendes Problem:
Ich habe zwei Tabellen in der Datenbank angelegt.
Tabelle1 -> *TEST_CUSTOMER
-ID* _ PK, NOT NULL_
*-NAME   * _NULL_
*-EMAIL  * _ NULL_

Tabelle2 ->*TEST_ITEM *
_*-ID                *PK, NOT NULL_
*-NAME           *_NULL                 
*-SELLER_ID   *FK_SELLER2 (auf TEST_CUSTOMER_ID ), NULL* 
-BUYER_ID    *FK2_BUYER2 (auf TEST_CUSOMER_ID), NULL_


Die Tabelle 2 (TEST_ITEM) hat zwei Felder mit den FK`s (SELLER_ID, BUYER_ID) dieser Felder sind aber *NULLABEL*

Das Problem ist, dass wenn ich mit JPA ein Object Item (ohne FK`s auf Customer) erstelle und dieser per persist() in die Datenbank abspeichern will, kommt es zur der Fehlermeldung:

_*[EL Warning]: 2016-03-21 21:23:38.769--UnitOfWork(891232836)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (ONLINESHOP.FK_BUYER2) violated - parent key not found

Error Code: 2291
Call: INSERT INTO onlineshop.TEST_ITEM (ID, BUYER_ID, NAME, SELLER_ID) VALUES (?, ?, ?, ?)
    bind => [4 parameters bound]
Query: InsertObjectQuery(Item@f4cfd90)
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (ONLINESHOP.FK_BUYER2) violated - parent key not found

Error Code: 2291
Call: INSERT INTO onlineshop.TEST_ITEM (ID, BUYER_ID, NAME, SELLER_ID) VALUES (?, ?, ?, ?)
    bind => [4 parameters bound]
Query: InsertObjectQuery(Item@f4cfd90)*_

So wie ich die Fehlermeldung verstehe, werden die FK`s  verlangt.
Was ich aber nicht verstehe, WARUM, diese zwei Felder sind doch NULLABLE.
Per Insert in der Datenbank selber, scheint es zu funktionieren ( _i__nsert into TEST_ITEM (ID,NAME)
values (1,'DVD');  ). 
_
Kann mir jemand evtl. bei diesem Problem helfen.
Hier sind noch meine Java-Klassen bzw Code.

*Customer.class*

```
@Entity
@Table(schema="ONLINESHOP", name="TEST_CUSTOMER")
public class Customer  implements Serializable{

    @Id
    @SequenceGenerator(name="CUSTOMER_ID_GEN", 
                      sequenceName="seq_TEST_CUSTOMER",
                      allocationSize=1,
                      initialValue=1,
                      schema="ONLINESHOP")
    @GeneratedValue(strategy=GenerationType.SEQUENCE,
    generator="CUSTOMER_ID_GEN")
    private int id;
   
    private String name;
   
    private String email;
   
    private Set<Item> items;

//------------------------------------------------------------------------------------------------------------------------   
   

    public Customer() {
       
    }

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Set<Item> getItems() {
        return items;
    }

    public void setItems(Set<Item> items) {
        this.items = items;
    }
   
   
   
   
}
```

*Item.class*

```
@Entity
@Table(schema="onlineshop", name="TEST_ITEM")
public class Item implements Serializable {
   
   
    @Id
    @SequenceGenerator(name="ITEM_ID_GEN",
                      sequenceName="seq_TEST_ITEM",
                      allocationSize=1,
                      initialValue= 1,
                      schema="ONLINESHOP")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ITEM_ID_GEN")
    private int id;
   
    private String name;
   
    @Column(name="SELLER_ID")
    private int verkaufer_id;
    @Column(name="BUYER_ID")
    private int kaufer_id;

       
    public Item() {
       
    }
   
   
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getVerkaufer_id() {
        return verkaufer_id;
    }
    public void setVerkaufer_id(int verkaufer_id) {
        this.verkaufer_id = verkaufer_id;
    }
    public int getKaufer_id() {
        return kaufer_id;
    }
    public void setKaufer_id(int kaufer_id) {
        this.kaufer_id = kaufer_id;
    }
       
}
```

*Main.class*

```
public class Tester {

    public static void main(String[] args) {
       
       
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA_2");
        EntityManager manager = emf.createEntityManager();
               
        Item item1 = new Item();
        item1.setName("DVD");
       
        try
        {       
            manager.getTransaction().begin();               
           
            manager.persist(item1);
           
            manager.getTransaction().commit();           
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
        }
       
       
    }

}
```


----------



## mrBrown (21. Mrz 2016)

deine FKs sind ints, die sind per Default 0, was nicht das NULL der Datenbank ist.
Du versucht mit Fk 0 zu adden, 0 gibt es aber nicht als key in der referenzierten Tabelle 

Edit:
Sinnvollerweise referenziert man die anderen Objekte nicht mehr als FK, sondern als Referenz auf das Objekt, in dem Fall dann mit @ManyToOne, Um FK und laden der Objekte kümmert sich dann das Framework


----------



## bizkit (22. Mrz 2016)

Klar, hab ich garnicht bedacht dass Int 0 ist 

Ich danke dir auf jeden Fall für dein Hilfe.

Jetzt habe ich das mit @ManyToOne umgesetzt 
bekomme aber folgenden Fehler:

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [onlineshop.TEST_ITEM.SELLER_ID].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[seller]
Descriptor: RelationalDescriptor(Item --> [DatabaseTable(onlineshop.TEST_ITEM)])

Kannst du mir evtl. da auch helfen? 

Die beiden Klassen habe ich jetzt geändert.
Diese sehen wie folgt aus:

Customer:

```
@Entity
@Table(schema="ONLINESHOP", name="TEST_CUSTOMER")
public class Customer  implements Serializable{

    @Id
    @SequenceGenerator(name="CUSTOMER_ID_GEN", 
                      sequenceName="seq_TEST_CUSTOMER",
                      allocationSize=1,
                      initialValue=1,
                      schema="ONLINESHOP")
    @GeneratedValue(strategy=GenerationType.SEQUENCE,
    generator="CUSTOMER_ID_GEN")
    private int id;
   
    private String name;
   
    private String email;

  
    public Customer() {
       
    }

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
```

Item:


```
@Entity
@Table(schema = "onlineshop", name = "TEST_ITEM")
public class Item implements Serializable {

    @Id
    @SequenceGenerator(name = "ITEM_ID_GEN", sequenceName = "seq_TEST_ITEM", allocationSize =        1, initialValue = 1, schema = "ONLINESHOP")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ITEM_ID_GEN")
    private int id;

    private String name;

    @Column(name = "SELLER_ID")
    private int seller_id;
    @Column(name = "BUYER_ID")
    private int buyer_id;


    @ManyToOne
    //@JoinColumn(name="SELLER_ID")
    private Customer seller;

    public Item() {

    }

    public Customer getSeller() {
        return seller;
    }

    public void setSeller(Customer seller) {
        this.seller = seller;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSellerID() {
        return seller_id;
    }

    public void setSellerID(int seller_id) {
        this.seller_id = seller_id;
    }

    public int getBuyerID() {
        return buyer_id;
    }

    public void setBuyerID(int buyer_id) {
        this.buyer_id = buyer_id;
    }

}
```


----------



## mrBrown (22. Mrz 2016)

@Column(name = "SELLER_ID")
    private int seller_id;

ist überflüssig, da das Feld in der Datenbank durch die ManyToOne-Beziehung selbst angelegt wird. Ich hab den Fehler noch nie gesehen, denke aber das liegt daran, die Beziehung legt ein passendes Feld an, und du selbst noch mal


----------

