Hibernate 'Refresh' ?

janus23

Mitglied
Hallo :)

Folgende Situation:
Ich habe die Klasse Folder:
Java:
@Entity
@Table
public class Folder implements Serializable {
    
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int folderID;
    
    @ManyToOne
    private User user;
    
    @Column(nullable=false)
    private String name;
    
    @OneToMany(mappedBy = "folder")
    private List<Message> messages;
}

Und die Klasse Message:
Java:
@Entity
@Table

public class Message implements Serializable {
    
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int mgid;
    
    
    @ManyToOne
    private Folder folder;
    
    @Column(nullable=false)
    private String subject;
    
    @Column(nullable=false)
    private String message;
    

    @ManyToOne
    private User sender;
  
    @ManyToOne
    private User receiver;
    
    @Column(nullable=false)
    private Timestamp sendTime = new Timestamp(System.currentTimeMillis());
    
    @Column(nullable=false)
    private boolean wasRead = false;
    
    @Column(nullable=false)
    private boolean isDeleted = false;
}

Wie man stehen Message und Folder in einer Beziehung, was ja auch funktioniert.
Wenn ich jetzt eine neue Message hinzufüge, mit
Java:
    public void addMessage(Message m){
        Session se = sf.openSession();
        Transaction ta = se.beginTransaction();
        
        se.save(m);
        
        ta.commit();
        se.close();
    }

Wird die Message ganz normal der Datenbank hinzugefügt. Jedoch erneuert Hibernate den Inhalt der message List in der Folder list nicht automatisch.
Gibt es eine Funktion die ich aufrufen kann, damit Hibernate die Messages bei jedem Seitenaufruf neu lädt, damit sie auch tatsäich sofort in der Liste sind?
 
N

nillehammer

Gast
Nein, Hibernate macht das nicht selbständig. Du bist auf Objektebene (also in der Java-Welt) selbst dafür verantwortlich, dass alle Relationen gültig sind. Bei einer bidirektionalen Relation wie hier musst Du also selbst beide Seiten gültig machen. Implementiere dafür die add-Methode innerhalb von Folder und nicht als DAO-Methode. Füge dort die neue Message in die Liste ein und sorge innerhalb der add-Methode gleichzeitig dafür, dass bei Message der Folder gesetzt wird. Speichere dann erst mit Hibernate.
 
Zuletzt bearbeitet von einem Moderator:

janus23

Mitglied
Gut, entweder versteh ich was nicht oder ich mach was falsch. Gut, es leuchtet mir ein was falsch ist, aber naja xD

Java:
    public String sendNewMessage()
    {
        User receiver = userDB.getUserByName(receiverInput);
        if(receiver != null)
        {
            Folder inbox = receiver.getFolderByName("Posteingang");
            Folder outbox = currentUser.getFolderByName("Postausgang");
            
            Message msgForReceiver = new Message(inbox, subjectInput, textInput, currentUser, receiver);
            Message msgForSender = new Message(outbox, subjectInput, textInput, currentUser, receiver);
            msgForSender.setWasRead(true);
            
            inbox.addMessage(msgForReceiver);
            outbox.addMessage(msgForSender);
            
            
            msgDB.addMessage(msgForSender);
            msgDB.addMessage(msgForReceiver);
            
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Die Nachricht wurde erfolgreich verschickt!"));
        }else{
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Der Empfänger existiert nicht!"));
        }
        
        return "";
    }
Das ist die send Methode. Ich hol mir den Empfänger aus der db, füge die Message zu den Folder hinzu, und speichere das ganze.

Jetzt ist aber das Problem, das ich den User aus der Database hole. Das heißt die Liste die da in dem Projekt ist, ist ja dann eine andere wie von einem User der gerade eingeloggt ist, oder ?
Wie soll ich das nun lösen? Alle eingeloggten user in einer Bean speichern und dort meine Operationen ausführen?
 
N

nillehammer

Gast
Jetzt ist aber das Problem, das ich den User aus der Database hole. Das heißt die Liste die da in dem Projekt ist, ist ja dann eine andere wie von einem User der gerade eingeloggt ist, oder ?
Wie soll ich das nun lösen? Alle eingeloggten user in einer Bean speichern und dort meine Operationen ausführen?
Wenn ich Deinen Code richtig verstehe, ist reciever der User, den Du aus der Datenbank holst. Der hat doch mit dem gerade eingeloggten User currentUser (also dem sender) überhaupt nichts zu tun. Der Status von currentUser ist (soweit ich das sehe) auch korrekt, weil Du in dem Code die Messages erzeugtst und der Outbox des Users zuweist. Wo ist also das Problem?
 

janus23

Mitglied
Angenommen User A schickt User B eine Nachricht.
CurrentUser ist der User der gerade eingeloggt ist. Dieser ist in der Klasse NewMessageBean ein ManagedProperty der Klasse LoginProperty, in der ich das User Objekt speichere.
Angenommen User B ist auch eingeloggt. A schickt B eine Nachricht. A ist currentUser, und in diesem outbox wird eine Nachricht hinzugefügt. Da ja der Ordner im currentUser Objekt enthalten ist, ist das kein Problem, da dieses Object auch zur Anzeige verwendent wird.
Der Receiver kommt jedoch aus der Datenbank, und steht nicht im Bezug zum Objekt, das erstellt wird, wenn sich User B einloggt. Damit User B die Nachricht also in der Inbox sieht, müsste ich doch auf das currentUser Objekt von User B zugreifen können.
Oder nicht?
 
N

nillehammer

Gast
Ah ok, so weit habe ich nicht gedacht, dass Sender und Reciever gleichzeitig eingeloggt sind. Danke für die Erklärung. Das ist natürlich ein Problem. Mein Vorschlag ist, jedes Mal vor Anzeige der View für die Inbox des Users die Messages aus der Datenbank zu laden (ja, hast richtig gelesen, jedes Mal). Die Datenbank ist der einzige Ort, wo alle Informationen valide zusammenlaufen.

Wenn Du Dir jetzt Gedanken wg. Performance machst, es wird wahrscheinlich nie ein Problem werden. Falls doch und erst dann setze Hibernates 2nd-Level Cache ein. Von eigenimplementierten Cachingmechanismen über ApplicationScope oder so rate ich dringenst ab. Da verplemperst Du ganz viel Zeit mit Status-Synchronisation, was woher laden etc. Und am Ende platzt Dir vielleicht noch die Anwendung selbst, weil Du Dir den RAM zumüllst oder sie lässt sich nicht im Cluster betreiben oder, oder...
 
Zuletzt bearbeitet von einem Moderator:

janus23

Mitglied
Mein Vorschlag ist, jedes Mal vor Anzeige der View für die Inbox des Users die Messages aus der Datenbank zu laden (ja, hast richtig gelesen, jedes Mal). Die Datenbank ist der einzige Ort, wo alle Informationen valide zusammenlaufen.

Das war auch meine Idee wie ich den Thread erstellt habe, ich fürchte nur ich hab mich unklar ausgedrückt. Ich wollte wissen ob es eine Funktion gibt die jedes mal praktisch den Inhalt erneuert. Das wär nämlich praktisch gewesen. So muss ich es halt selbst machen, auch kein großes Problem :)

Danke für die Hilfe ;)
 

Oben