JPA GAE OneToOne

Diskutiere GAE OneToOne im Data Tier Forum; Hallo Forum, ich versuche nun seit geraumer Zeit eine einfache OneToOne-Beziehung ans laufen zu bekommen. Leider entstehen immer diverse...

  1. manuell
    manuell Neues Mitglied
    Hallo Forum,

    ich versuche nun seit geraumer Zeit eine einfache OneToOne-Beziehung ans laufen zu bekommen.
    Leider entstehen immer diverse Fehler und ich komme auf keinen grünen Zweig.
    Die Herrausforderung ist folgende, ich möchte einen Benutzer anlegen, dann soll der Benutzer durch ein Event ein UserProfil bekommen (d.h. es existiert auch ein Benutzer ohne UserProfile).

    Aktuell habe ich folgendes:

    Code (Java):


    @Entity
    public class UserProfile {
        @OneToOne(mappedBy="userProfile")
        private User user;  
       
        private int id;
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
    ...
     
    und User
    Code (Java):

    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
        private String username;
        private String email;  
        @OneToOne
        private UserProfile userProfile;
       
       
        public UserProfile getUserProfile() {
            return userProfile;
        }
        public void setUserProfile(UserProfile userProfile) {
            this.userProfile = userProfile;
        }
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    ...
     
    Beim Anlegen vom Benutzer passiert jetzt folgendes:
    Code (Java):

    INFO: Local Datastore initialized:
        Type: Master/Slave
        Storage: C:\Users\manuell\workspace\projekt\war\WEB-INF\appengine-generated\local_db.bin
    03.01.2013 07:01:16 com.google.appengine.api.datastore.dev.LocalDatastoreService load
    INFO: The backing store, C:\Users\manuell\workspace\projekt\war\WEB-INF\appengine-generated\local_db.bin, does not exist. It will be created.
    03.01.2013 07:01:17 org.datanucleus.state.JDOStateManager setPostStoreNewObjectId
    SCHWERWIEGEND: java.lang.NullPointerException
    03.01.2013 07:01:47 com.google.appengine.api.datastore.dev.LocalDatastoreService$PersistDatastore persist
    INFO: Time to persist datastore: 309 ms
     
    Ich habe als id auch schon Long / long als id benutzt, führte allerdings zu anderen Fehlern :)
    Wäre super wenn jemand ein funktionierendes Beispiel (für gae) hat.

    Danke für die Hilfe
     
  2. Vielleicht hilft dir dieser Java-Kurs hier weiter --> (hier klicken)
  3. Ullenboom
    Ullenboom Mitglied
    Deine Beziehung ist bidirektional. Hast du beide Seite verbunden? Also so was wie

    User u = new User();
    UserProfile p = new UserProfile();
    u.setUserProfile(p);
    p.setUser(u);
     
  4. manuell
    manuell Neues Mitglied
    Hi,

    also den User kann ich problemlos anlegen und auch persistieren.
    Allerdings kann ich den Benutzer dann nicht auslesen
    so z.B.
    Code (Java):

    Query query = em.createQuery("SELECT u FROM User u WHERE u.email =:arg1");
            query.setParameter("arg1", email);
            User user;
            user = (User)query.getSingleResult();
     
    aber dann:
    Code (Java):

    java.lang.NullPointerException
        at com.google.appengine.datanucleus.query.QueryEntityPKFetchFieldManager.fetchLongField(QueryEntityPKFetchFieldManager.java:74)
        at org.datanucleus.identity.IdentityUtils.getApplicationIdentityForResultSetRow(IdentityUtils.java:101)
        at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1009)
     
    Bin mir nicht sicher an welcher Stelle ich das UserProfil setzen soll, brauche es ja erst später und nicht beim ersten persistieren.

    Danke für die Hilfe
     
  5. Templarthelast
    Templarthelast Mitglied
    Hat das Entity für UserProfile auch eine OneToOne Annotation mit einem Userobjekt? Ich vermute, dass du automatisch eager loading hast und beim Auslesen des Users auf das UserProfile geladen werden soll, was nicht gesetzt ist und deshalb eine NPE wirft.

    Poste am besten mal die UserProfile Klasse. Als weitere Fehlersuche würde ich mal die OneToOne cascade auf lazy setzen bzw. einfach mal versuchen, ob ich nur den Benutzernamen per Query erhalten kann.

    Code (SQL):
    SELECT u.username FROM USER u WHERE u.email := email
     
  6. manuell
    manuell Neues Mitglied
    Also,
    ich habe die UserProfile jetzt mal etwas angepasst und sie sieht jetzt wie folgt aus:
    Code (Java):

    @Entity
    public class UserProfile {
        @OneToOne(mappedBy="userProfile")
        private User user;
       
        @Id
        private Key key;
       
        public Key getKey() {
            return key;
        }
        public void setKey(Key key) {
            this.key = key;
        }
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
    }
     
    Ist jetzt wirklich nur für Testzwecke.
    Die User sieht so aus:
    Code (Java):

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
        private String username;
        private String email;  
        @OneToOne
        private UserProfile userProfile;
           
        public UserProfile getUserProfile() {
            return userProfile;
        }
        public void setUserProfile(UserProfile userProfile) {
            this.userProfile = userProfile;
        }
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
            public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
    }
     
    auch erstmal aufs nötigste reduziert.
    Das ist meine EMF-Klasse:
    Code (Java):

    public class EMF {
        private static final EntityManagerFactory emfInstance = Persistence
                .createEntityManagerFactory("transactions-optional");
     
        private EMF() {
        }
     
        public static EntityManagerFactory get() {
            return emfInstance;
        }
    }
     
    so erzeuge ich den User:
    Code (Java):

    User newUser = new User();
    newUser.setUsername(Username);
    newUser.setEmail(Email);
    EntityManager em = EMF.get().createEntityManager();
    em.persist(newUser);
    em.close();
     
    Das klappt noch problemlos. (bis auf ein paar Warnungen)
    Sehe gerade das beim Abrufen des Benutzers folgende Warnung kommt:
    Code (Java):

    The datastore does not support joins and therefore cannot honor requests to place related objects in the default fetch group.  The field will be fetched lazily on first access.  You can modify this warning by setting the datanucleus.appengine.ignorableMetaDataBehavior property in your config.  A value of NONE will silence the warning.  A value of ERROR will turn the warning into an exception.
     
    beim nächsten Abrufen kommt dann der Fehler:
    Code (Java):

    java.lang.NullPointerException
        at com.google.appengine.datanucleus.query.QueryEntityPKFetchFieldManager.fetchLongField(QueryEntityPKFetchFieldManager.java:74)
        at org.datanucleus.identity.IdentityUtils.getApplicationIdentityForResultSetRow(IdentityUtils.java:101)
        at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1009)
     
    zur Sicherheit hier nochmal die persistence.xml
    Code (Java):

    <?xml version="1.0" encoding="UTF-8" ?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
            http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">

        <persistence-unit name="transactions-optional">
            <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
            <properties>
                <property name="datanucleus.NontransactionalRead" value="true"/>
                <property name="datanucleus.NontransactionalWrite" value="true"/>
                <property name="datanucleus.ConnectionURL" value="appengine"/>
            </properties>
        </persistence-unit>
    </persistence>
     
    ...Bin echt überfragt :)
     
  7. Templarthelast
    Templarthelast Mitglied
    Die UserProfile Entity hat keine Id Generation Strategy weshalb die Id in der Datenbank nicht gesetzt wird und somit die Verbindung nicht funktionieren kann. Meistens hilft es auch mal die wirkliche generierten Datenbankwerte anschaut. Desweiteren solltest du dem Userobjekt auch ein UserProfile zuweisen.
     
Die Seite wird geladen...

GAE OneToOne - Ähnliche Themen

Hibernate / JPA OneToOne MappedBy Frage
Hibernate / JPA OneToOne MappedBy Frage im Forum Datenbankprogrammierung
OneToOne Relation
OneToOne Relation im Forum Data Tier
OneToOne Beziehung erzeugt not marked cascade PERSIST
OneToOne Beziehung erzeugt not marked cascade PERSIST im Forum Data Tier
Hibernate Annotation @OneToOne Fremdschlüssel
Hibernate Annotation @OneToOne Fremdschlüssel im Forum Datenbankprogrammierung
Cannot add or update a child row - javax.persistence.OneToOne
Cannot add or update a child row - javax.persistence.OneToOne im Forum Web Tier
Thema: GAE OneToOne