# [Hibernate]1:1 Beziehung



## hyperion (16. Feb 2011)

Hallo,

so endlich passiert auch mal was bei meiner Anwendung.
Ich habe zwei Tabellen. 
User:
-User_id
-LoginName
-LoginPassword
-Mail
-RegisterDate
-Person_ID

Person:
-Person_ID
-Name
-FirstName
-Birthday

Entsprechend der Tabellen habe ich zwei Klassen Person und User. Nun möchte ich Objekte dieser Klassen in die Datenbank eintragen. Ich habe dazu eine Registrierungsseite erstellt, welche die Eigenschaften füllt.
Mit der Methode register() stoße ich dann das Registrieren an und es funktioniert sogar fast. Es wird jeweils ein Datensatz je Tabelle angelegt, allerdings ist das Feld Person_ID in der Tabelle User leer. Ich denke hier fehlt noch irgendwas bei den Annotations. Könnt Ihr mir da noch mal helfen?


```
@Entity
public class Person implements Serializable{

     @Id
     @Column(name = "ID", nullable = false)
     @GeneratedValue(strategy=GenerationType.AUTO)
     @NotNull
     private Integer id;

     @Column(name = "Name", nullable = false)
     @NotNull
     private String name;

     @Column(name = "FirstName", nullable = false)
     @NotNull
     private String firstName;

    @Column(name = "Birthday", nullable = true)
    @Temporal(javax.persistence.TemporalType.DATE)
    @Past
    private Date birthday;

     public Person(){
         
     }
     
     ...Getter und Setter...
}
```


```
@Entity
@Table(name="User")
@SequenceGenerator(name="ID", initialValue=1, allocationSize=1)
public class User implements Serializable{

    @Column(name = "ID", nullable = false)
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @NotNull
    private int id;

    @Column(name = "LoginName", nullable = false)
    @NotNull
    private String loginName;

    @Column(name = "LoginPassword", nullable = false)
    @NotNull
    private String loginPassword;

    @NotNull
    @OneToOne
    @JoinColumn(name="Person_ID")
    private Person person;

    @Column(name = "Mail", nullable = false)
    @NotNull
    private String mail;

    @Column(name = "RegisterDate", nullable = false)
    @Temporal(javax.persistence.TemporalType.DATE)
    @NotNull
    private Date registerDate;

   ...Getter und Setter...
}
```

Gruß hyperion


----------



## jwiesmann (16. Feb 2011)

ich glaub das richtige Tag wäre

```
@OneToOne(mappedBy = "Person_ID")
private Person person;
```


Des Weiteren fehlt doch in Person noch die Referenz zu User

```
@OneToOne(mappedBy = "Person_ID")
private User user;
```

aber ich bin mir absolut nicht sicher


----------



## Raum114 (16. Feb 2011)

Mappins sind scheinbar ok, kannst du die Methode mal posten mit der du speicherst?


----------



## jwiesmann (16. Feb 2011)

Ich hab leider nix da mit Hibernate .. 
aber grundsätzlich wäre es wie folgt:


```
User u = new User();
u.set..

Person p = new Person();
p.set...

em.persist(p);

u.setPerson(p);
em.persist(u);
```
Das sollte schon reichen .. grob .. halt


----------



## Raum114 (16. Feb 2011)

Wie ist's so (schematisch):

em.persist(u);
em.persist(p);
u.setPerson(p);
tx.commit()
em.close()


----------



## hyperion (16. Feb 2011)

Hallo,

hmm scheinbar verwendet Ihr da andere Methoden. 
Bei mir sieht das so aus:

```
public String register(){

       user.setRegisterDate(new Date());
       Transaction tx = null;
       Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
       try {
          tx = session.beginTransaction();
          session.save(person);
          session.save(user);
          tx.commit();
          return "success";
        } catch (RuntimeException e) {
          if (tx != null && tx.isActive()) {
            try {
    // Second try catch as the rollback could fail as well
              tx.rollback();
            } catch (HibernateException e1) {

            }
    // throw again the first exception
            throw e;
          }
        }
       return "failed";
    }
```

Von welchem Typ ist em?

Gruß hyperion


----------



## KSG9|sebastian (17. Feb 2011)

em = EntityManager

EntityManager ist aus JPA und entspricht mehr oder minder der Session aus Hibernate.

Hast du die Ratschläge befolgt?

1. mappedBy
2. @OneToManny
3. Cascade versucht?

@OneToMany( cascade = {CascadeType.ALL} )


----------



## X5-599 (18. Feb 2011)

Ein paar Dinge von mir:

Das mapping von user zu person in der Klasse User sieht schon ganz gut aus:


```
@OneToOne
@JoinColumn(name="Person_ID")
private Person person;
```

Aber das id Feld sollte so aussehen:


```
@Column(name = "User_id", nullable = false)
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
```

Wegen dem GenerationType.AUTO bin ich mir nicht 100% sicher, da ich für gewöhnlich GenerationType.SEQUENCE mit Datenbankseitigen Sequenzen benutze. Auch habe ich die @NotNull Annotation weggelassen, denn nach meinem Wissensstand ist das dasselbe wie der Zusatz nullable = false in der @Column/@JoinColumn Annotation. (Bitte berichtigen, wenn ich falsch liege)

In der Person Klasse müsste das id Feld ebenfalls geändert werden:


```
@Column(name = "Person_ID", nullable = false)
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
```

Die @NotNull Dinger würde ich auch hier alle entfernen.

Nochmal: Ich habe noch nie mit GenerationType.AUTO gearbeitet. Aber so wie ich es verstehe muss der _name = "attribut_id"_ in der @Column Annotation derselbe sein wie in der entsprechenden Tabelle.


Und zu dem Vorschlag mit dem mappedBy:
Sowas macht man, wenn man eine bi-direktionale Beziehung aufbauen möchte. Am Beispiel hier:

Im Moment hat 1 User-Objekt 1 Person-Objekt
Ein User-Objekt weiss also genau welches Person-Objekt zu ihm gehört. Ein Person-Objekt weiss aber *nicht* zu welchem User-Objekt es gehört...
Um das zu erreichen muss man in der Klasse Person folgendes haben:


```
@OneToOne(mappedBy = "person")
private User user;
```

Das ist auch schon alles. Ein mappedBy auf *beiden* Seiten der Beziehung kann nicht funktionieren! Auch muss das mappedBy einen Attributsnamen(hier: person) angeben. Keine Tabellenspalte. Das sagt Hibernate das die Beziehung zu User bereits in der User Klasse durch das person-Attribut realisiert wurde.


Soweit dazu. Ich bin bei weitem kein Experte auf dem Gebiet, und das was ich hier geschrieben habe basiert auf meinen eigenen Erfahrungen mit Hibernate.

*Bitte um Korrektur, falls etwas grundlegend Falsches dabei war!*


Gruß


----------



## hyperion (19. Feb 2011)

Hallo,

also es funktioniert jetzt:

User

```
@Entity
@Table(name="User")
public class User implements Serializable{

    @Column(name = "User_ID", nullable = false)
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "LoginName", nullable = false)
    private String loginName;

    @Column(name = "LoginPassword", nullable = false)
    private String loginPassword;

    @ManyToOne
    @JoinColumn(name="Person_ID")
    private Person person;

    @Column(name = "Mail", nullable = false)
    private String mail;

    @Column(name = "RegisterDate", nullable = false)
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date registerDate;
}
```

Person

```
@Entity
@Table(name="Person")
public class Person implements Serializable{

     @Id
     @Column(name = "Person_ID", nullable = false)
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Integer id;

     @Column(name = "Name", nullable = false)
     private String name;

     @Column(name = "FirstName", nullable = false)
     private String firstName;

     @OneToOne(mappedBy="person")
     private User user; 

    @Column(name = "Birthday", nullable = true)
    @Temporal(javax.persistence.TemporalType.DATE)
    @Past
    private Date birthday;
```

register

```
public String register(){

       user.setRegisterDate(new Date());
       Transaction tx = null;
       Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
       try {
          tx = session.beginTransaction();
          user.setPerson(person);
          person.setUser(user);
          session.save(person);
          session.save(user);
          tx.commit();
          return "success";
        } catch (RuntimeException e) {
          if (tx != null && tx.isActive()) {
            try {
    // Second try catch as the rollback could fail as well
              tx.rollback();
            } catch (HibernateException e1) {

            }
    // throw again the first exception
            throw e;
          }
        }
       return "failed";
    }
```

Gruß hyperion


----------

