JSF Nochmal ACL -+- Neue Entity aus anderen Entitys erstellen

Bitte aktiviere JavaScript!
Guten Tag zusammen !!

Ich hab hier im Forum ja schon echt super Hilfe für mein Projekt bekommen da muss ich erstmal echt ein Lob aussprechen :toll:

Ich habe gerade ein kleines Problem.
Ich habe mehrere Entity Objekte (ACL,Benutzer,Gruppe,Methode)

Ein ACL Objekt besteht aus jeweils einem Eintrag der Objekte (Methode, Gruppe, Benutzer).

Die Einträge (Benutzer,Gruppe) können "null" sein, der Eintrag Methode hingegen nicht.

Die Darstellung der Tabellen in Tables oder Selectboxen klappt super, aber beim erstellen eines neuen
ACL Objektes habe ich das Problem das auch gleichzeitig ein neues Methoden,Gruppen und Benutzer Objekt erstellt und persisiert wird. Dadurch erhalte ich unnötige redundanz in meinen Tabellen(Methode,Gruppe,Benutzer)... :-(

Hier einmal ein Bild wie es sein sollte(ACL eintrag manuell erstellt):

001.JPG


Und hier wie es wirklich ist:

002.JPG


Mann sieht auf dem 2ten bild das der ACL Eintrag zwar in dem Sinne korekt ist, aber nicht die auf die vorhandenen Objekte referenziert und stattdessen neue erstellt.... :-/

Ich glaube das es daran liegt das ich in meinem PresentationModell neue Objekte erstelle und diese dann dem Objekt ACL hinzufüge....

Java:
package com.alex.aclgenerator;

import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

/**
 *
 * @author schmack
 */
@Named
@RequestScoped
public class AclPM {
    
    private Methode  pm_methode  = new Methode();
    private Gruppe   pm_gruppe   = new Gruppe();
    private Benutzer pm_benutzer = new Benutzer();
    private Acl      pm_acl      = new Acl();
    
    @EJB
    AclBean bean;
    
    
//---------------------------------------------------

    public Methode getPm_methode() {
        return pm_methode;
    }

    public void setPm_methode(Methode pm_methode) {
        this.pm_methode = pm_methode;
    }

    public Gruppe getPm_gruppe() {
        return pm_gruppe;
    }

    public void setPm_gruppe(Gruppe pm_gruppe) {
        this.pm_gruppe = pm_gruppe;
    }

    public Benutzer getPm_benutzer() {
        return pm_benutzer;
    }

    public void setPm_benutzer(Benutzer pm_benutzer) {
        this.pm_benutzer = pm_benutzer;
    }

    public Acl getPm_acl() {
        return pm_acl;
    }

    public void setPm_acl(Acl pm_acl) {
        this.pm_acl = pm_acl;
    }
    
    
    public List<Methode> getMethods() {
    return bean.getMethods();
    }
    
    public List<Benutzer> getUsers() {
    return bean.getUsers();
    }
    
    public List<Gruppe> getGroups() {
    return bean.getGroups();
    }
    
    public List<Acl> getAcls() {
    return bean.getAcls();
    }
    
    

//---------------------------------------------------------
    
    public void storeMethod(){
        System.out.println("Methode gespeichert!");
        bean.addEntry(pm_methode);
    }

    public void storeGroup(){
        System.out.println("Gruppe gespeichert!");
        bean.addEntry(pm_gruppe);
    }

    public void storeUser(){
        System.out.println("Benutzer gespeichert!");
        bean.addEntry(pm_benutzer);
    }
    
    public void storeAcl(){
        pm_acl.setMethode(pm_methode);
        pm_acl.setGruppe(pm_gruppe);
        pm_acl.setBenutzer(pm_benutzer);
        
        bean.addAcl(pm_acl);
        
        System.out.println("ACL gespeichert!");
    }
    
}//endclass
ich würde aber gerne auf die Objekte referenzieren die ich schon in der Selectbox habe....

003.JPG

HTML:
               <p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode.name}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.methods}" var="method"
                                   itemValue="#{method.name}" itemLabel="#{method.name}" />
                </p:selectOneMenu>            

               <p:selectOneMenu id="selectone_groups" value="#{aclPM.pm_gruppe.name}"
                                 style="margin-left: 5px;">
                   <f:selectItems value="#{aclPM.groups}" var="group"
                                  itemValue="#{group.name}" itemLabel="#{group.name}" />
                </p:selectOneMenu>

               <p:selectOneMenu id="selectone_users" value="#{aclPM.pm_benutzer.name}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.users}" var="user"
                                   itemValue="#{user.name}" itemLabel="#{user.name}" />
                </p:selectOneMenu>

....und keine neuen erstellen......

Aber wenn ich in der Methode storeAcl() mit gettern anstatt settern versuche zu arbeiten geht das auch nicht.....:bahnhof:

Ich hoffe ich habe mich einigermaßen verständlich ausgedrückt und hoffe ihr kölnnt mir hier weiterhelfen...

Grüße, Alex !!
 
Zuletzt bearbeitet:
Du legst ja auch jedes Mal neue Objekte in deiner BusinessLogik an und setzt nur die Attribute auf diejenigen Werte, die anderen Einträge in deiner Datenbank bereits haben.

Nutze stattdessen dein selectOneMenu, um direkt die Objekte zu setzen, und nicht deren Inhalt. Schaue dir dazu die Klasse SelectItem und Converter an.

Dein JSF code sollte danach ungefähr so aussehen:
HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode.name}">
    <f:selectItems value="#{aclPM.methodItems}" />
    <f:converter binding="#{...myConverter}" />
</p:selectOneMenu>
 
Du legst ja auch jedes Mal neue Objekte in deiner BusinessLogik an und setzt nur die Attribute auf diejenigen Werte, die anderen Einträge in deiner Datenbank bereits haben.
Huaaah... Ich versuche den Satz zu verstehen aber bekomme ihn nicht ganz in meinen Kopf....

Könntest Du mir das irgendwie veranschaulichen?

Die neuen Objekte im PM brauche ich ja auch um in der View die Tables und SelectBoxen füllen zu können, also entfernen kann ich die nicht... :-(

HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode.name}"
meinst du das ich hier vielleicht anstatt auf das Objekt pm_methode und das property name auf was anderes referenzieren sollte?


-----------------

mein selectItems Tag gibt eine List<Methode> aus, das ist doch ok oder?

Java:
    public List<Methode> getMethods() {
         Query query = em.createQuery("SELECT data FROM Methode data");        
         List<Methode> resultList = query.getResultList();         
        return resultList;
    }
 
Die neuen Objekte im PM brauche ich ja auch um in der View die Tables und SelectBoxen füllen zu können, also entfernen kann ich die nicht... :-(
Du sollst aber nicht einfach ein ganz neues Objekt erstellen und bei diesem dann den Namen setzen, sondern du setzt die Referenz auf genau einer der Objekte aus der Liste, die du auch ins SelectOneMenu steckst.
Insbesondere haben deine neu angelegten Objekte ja eine andere (bzw noch gar keine) ID, als die, die in der Datenbank stehen.

HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode.name}"
meinst du das ich hier vielleicht anstatt auf das Objekt pm_methode und das property name auf was anderes referenzieren sollte?

Ja, und zwar direkt auf pm_methode. Die Stelle ist mir beim anpassen den Codes durch die Lappen gegangen. Es sollte heißen:
HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode.name}"

mein selectItems Tag gibt eine List<Methode> aus, das ist doch ok oder?

Java:
    public List<Methode> getMethods() {
         Query query = em.createQuery("SELECT data FROM Methode data");        
         List<Methode> resultList = query.getResultList();         
        return resultList;
    }
Ja, fast ok. Was jedoch nicht ok ist, ist die Datenbank-Abfrage in der getter-Methode durchzuführen. Die getter-Methode sollte wirklich nur (!) die entsprechende Liste zurückgeben.
Initialisiere die Liste einmalig z.B. in einer PostConstruct-Methode (oder, sofern möglich, auch meinetwegen im Constructor).
 
HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode}"
!!!!!!!

Ich sollte echt mal schafen gehen..... :shock:
 
Hey stg :meld:

Danke für Deine Hilfe, weiss ich wirklich zu schätzen !! :applaus:

Aber weißt Du was? Ich glaube mein Problem liegt an einer ganz anderen Stelle.

Jedes Mal wenn ich ein neues Acl-Objekt erstelle, wird auch gleichzeitig ein neues Benutzer, Gruppen und Methoden Objekt erstellt.

So kann ja nur Redundanz entsehen...
Das liegt daran das ich die Entity ACL wie folgt aufgebaut habe:

Java:
@Entity
public class Acl implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="methode",nullable = true)
    private Methode methode;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="gruppe",nullable = true)
    private Gruppe gruppe;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="benutzer",nullable = true)
    private Benutzer benutzer;
       
    
//--------------------------------------------------    
    public Long getId() {
        return id;
    }

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

    public Methode getMethode() {
        return methode;
    }

    public void setMethode(Methode methode) {
        this.methode = methode;
    }

    public Gruppe getGruppe() {
        return gruppe;
    }

    public void setGruppe(Gruppe gruppe) {
        this.gruppe = gruppe;
    }

    public Benutzer getBenutzer() {
        return benutzer;
    }

    public void setBenutzer(Benutzer benutzer) {
        this.benutzer = benutzer;
    }
    

//--------------------------------------------------
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Acl)) {
            return false;
        }
        Acl other = (Acl) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "" + id;
    }
    
}
Ich habe den Aufbau aus einem JPA Buch und ich glaube daran müsste ich was ändern um das Problem zu lösen.

Was ich ja eigentlich will ist kein neues Objekt vom Typ Benutzer, Gruppe und Methode sondern nur die Referenz auf ein Attribut der ausgewählten Objekte.

Aber wie stelle ich das am besten dar?

Ok, die Objekte müssen aus der KLasse raus, oder?

Aber mache ich stattdessen dann Strings mit den Inhalten? Ne, oder??

Ich habs immer noch nicht ganz........:noe::rolleyes::bahnhof:
 
Och verdammt....

Ich habe jetzt die Entity Klasse Acl und das PresentationModel AclPM umgeändert:

Acl-Entity:
Java:
@Entity
public class Acl implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="methode",nullable = true)
    private String methodenname;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="gruppe",nullable = true)
    private String gruppenname;
    
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="benutzer",nullable = true)
    private String benutzername;

AclPM:
Java:
    public void storeAcl(){
        pm_acl.setMethodenname(pm_methode.getName());
        pm_acl.setGruppenname(pm_gruppe.getName());
        pm_acl.setBenutzername(pm_benutzer.getName());
        
        bean.addAcl(pm_acl);
        
        System.out.println("ACL gespeichert!");
    }

Leider geht das wohl auch nicht denn ich bekomme beim Deployen jedesmal diese Exception.....

Exception Description: [class com.alex.aclgenerator.Acl] uses a non-entity [class java.lang.String] as target entity in the relationship attribute [field gruppenname].

Muss ich jetzt ganz neue Entityklassen für meine ACL-Entity erstellen damit ich die Redundanz in den anderen Tabellen umgehen kann?

Grüße und einen schönen Guten Morgen !!!

Alex
 
Zuletzt bearbeitet:
[/code]

Was ich ja eigentlich will ist kein neues Objekt vom Typ Benutzer, Gruppe und Methode sondern nur die Referenz auf ein Attribut der ausgewählten Objekte.
Ja, genau!

Aber wie stelle ich das am besten dar?
Siehe Beitrag #2 und #4

Du bekommst eine Liste von z.B. Methoden von deinem JPA-Controller. Das Feld vom Typ Methode in deinem neuen Entity-Objekt, welches du anlegen möchtest, setzt du nun auf genau eine Methoden-Referenz aus dieser Liste (bzw kann das auch ein gänzlich neues Objekt sein, Hauptsache ist, dass der Vergleich mit equals true zurückgibt, aber du hast ja die Liste vorliegen, also wieso nicht einfach eins daraus auswählen)
Momentan nimmst du dir nur den Methoden-Namen und setzt diesen, was du aber machen solltest, ist die Methoden-Referenz zu setzen. Steht aber auch schon in Beitrag #4, nur mit dem Copy&Paste-fehler, den ich danach in Beitrag #5 verbessert habe :)
 
Zuletzt bearbeitet:
Ja, das hatte ich eigentlich schon verstanden....glaube ich ^^

Du bekommst eine Liste von z.B. Methoden von deinem JPA-Controller.
liste.jpg

Das Feld vom Typ Methode in deinem neuen Entity-Objekt, welches du anlegen möchtest, setzt du nun auf genau eine Methoden-Referenz aus dieser Liste
feld.jpg

Genau das mache ich doch, oder?
pm_acl ist ein neues Acl Objekt welches im der Klasse AclPM bereitgestellt wird.
Davon wähle ich das Feld Methode aus in welches geschrieben werden soll.

aber:

fehler.jpg

klappt nicht, der Eintrag wird nicht geschrieben.... (in glaube er findet die Einträge nicht)

und damit bin ich wieder auf dem stand von hier:
http://www.java-forum.org/web-tier/163646-mehrere-selectone-persistieren.html


;(;(;(
 
Zuletzt bearbeitet:
Haha....!!

Und das allerlustigste ist ja jetzt:

Ich hab mal die PrimeFaces Komponenten rausgenommen:

Code:
       <h:form id="form_selectOne">
           <h:panelGrid columns="5">
               
               <h:selectOneMenu id="selectone_methods" value="#{aclPM.pm_acl.methode}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.methods}" var="method"
                                   itemValue="#{method.name}" itemLabel="#{method.name}" />
                </h:selectOneMenu>            

               <h:selectOneMenu id="selectone_groups" value="#{aclPM.pm_acl.gruppe}"
                                 style="margin-left: 5px;">
                   <f:selectItems value="#{aclPM.groups}" var="group"
                                  itemValue="#{group.name}" itemLabel="#{group.name}" />
                </h:selectOneMenu>

               <h:selectOneMenu id="selectone_users" value="#{aclPM.pm_acl.benutzer}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.users}" var="user"
                                   itemValue="#{user.name}" itemLabel="#{user.name}" />
                </h:selectOneMenu>

               <h:commandButton value="create" action="#{aclPM.storeAcl()}" style="margin-left: 5px;"
                                >
                        <f:ajax execute="form_table_acls:table_acls" 
                                render="form_table_acls:table_acls"/>                  
               </h:commandButton>
               
           </h:panelGrid>
        </h:form>
damit klappt der speichern butten zwar, aber die redundanz bleibt :(:(

redundanz.JPG


P.S.: durch die vorgeschlagene Verwendung von den Entity-Feldern anstatt den direkten Propperties werden nun auch keine Daten (Name,Methode,Gruppe) mehr geschrieben sonder nur wie auf dem Bild zu sehen die IDs.....
 
Zuletzt bearbeitet:
PPS:

Falls Du in #4 gemeint hast ich soll direkt auf aclPM.pm_methode referenzieren anstatt wie oben auf aclPM.pm_acl.methode...... hab ich auch versucht.....

Code:
<h:form id="form_selectOne">

           <h:panelGrid columns="5">

               <h:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.methods}" var="method"
                                   itemValue="#{method.name}" itemLabel="#{method.name}" />
                </h:selectOneMenu>            

               <h:selectOneMenu id="selectone_groups" value="#{aclPM.pm_gruppe}"
                                 style="margin-left: 5px;">
                   <f:selectItems value="#{aclPM.groups}" var="group"
                                  itemValue="#{group.name}" itemLabel="#{group.name}" />
                </h:selectOneMenu>

               <h:selectOneMenu id="selectone_users" value="#{aclPM.pm_benutzer}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.users}" var="user"
                                   itemValue="#{user.name}" itemLabel="#{user.name}" />
                </h:selectOneMenu>

               <h:commandButton value="create" action="#{aclPM.storeAcl()}" style="margin-left: 5px;">
                                
                        <f:ajax execute="form_table_acls:table_acls" 
                                render="form_table_acls:table_acls"/>                  
               </h:commandButton>
               
           </h:panelGrid>
</h:form>

gleiches ergebnis.... :-(

003.JPG
 
Du wählst in deinem SelectOneMenu immer noch den Methodennamen und nicht die Methode selbst aus! (itemValue="#{method.name})

Wenn du alle meine Hinweise befolgst, dann sollte dein selectOneMenu in etwa so aussehen:

HTML:
<p:selectOneMenu id="selectone_methods" value="#{aclPM.pm_methode}">
    <f:selectItems value="#{aclPM.methodItems}" />
    <f:converter binding="#{..myConverter}" />
</p:selectOneMenu>
 
Macht das einen Unterschied? sieht nicht so aus..... :(


HTML:
       <h:form id="form_selectOne">
           <h:panelGrid columns="5">
               <h:selectOneMenu id="selectone_methods" value="#{aclPM.pm_acl.methode}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.methods}" var="method"
                                   itemValue="#{method}" itemLabel="#{method.name}" />
                </h:selectOneMenu>            

               <h:selectOneMenu id="selectone_groups" value="#{aclPM.pm_acl.gruppe}"
                                 style="margin-left: 5px;">
                   <f:selectItems value="#{aclPM.groups}" var="group"
                                  itemValue="#{group}" itemLabel="#{group.name}" />
                </h:selectOneMenu>

               <h:selectOneMenu id="selectone_users" value="#{aclPM.pm_acl.benutzer}"
                                 style="margin-left: 5px;">
                    <f:selectItems value="#{aclPM.users}" var="user"
                                   itemValue="#{user}" itemLabel="#{user.name}" />
                </h:selectOneMenu>

               <h:commandButton value="create" action="#{aclPM.storeAcl()}" style="margin-left: 5px;">
                        <f:ajax execute="form_table_acls:table_acls" 
                                render="form_table_acls:table_acls"/>                  
               </h:commandButton>
               <p:commandButton icon="ui-icon-refresh" update="form_selectOne"/>
           </h:panelGrid>
        </h:form>
005.JPG
 
Zuletzt bearbeitet:
wie sieht denn deine store-Methode nun aus?
Und Converter sehe ich da immer noch nicht, ich bezweifle, dass das so funktioniert, bzw wundere mich sogar, dass der da überhaupt was speichert...
 
Zuletzt bearbeitet:
wie sieht denn deine store-Methode nun aus?

Ich glaube unverändert....

Java:
    public void storeAcl(){
        pm_acl.setMethode(pm_methode);
        pm_acl.setGruppe(pm_gruppe);
        pm_acl.setBenutzer(pm_benutzer);
        
        bean.addAcl(pm_acl);
        
        System.out.println("ACL gespeichert!");
    }
Java:
    public void addAcl(Acl pm_acl) {     
        em.persist(pm_acl);
        System.out.println("ACL hinzugefügt!");
    }
Aber schau mal....

aa.jpg

Ein neues ACL Objekt führt immer zu neuen Objekten vom Typ Benutzer, Gruppe und Methode.
Das ist doch nicht gut oder??

----

Zum Konverter: Ich habe noch nicht ganz verstanden warum ich den brauche weil bisher klappt es auch so und in keinem Beispiel habe ich gesehen das jemand diese Komponente verwendet, ich müsste mich da auch erstmal in die Komponente einlesen und würde gerne erstmal mein bisheriges problem mit der Redundanz lösen ^^
 
Zuletzt bearbeitet:
Du setzt die Methode usw von pm_acl doch schon vorher (direkt) über dein SelectOneMenu, in deiner Store Methode schreibst du nun aber wieder andere Objekte darein.
Wir kommen offenbar leider wieder zu dem Punkt, dass OOP Grundlagen fehlen :(

Wenn du, wie dein Posting #14 vermuten lässt, direkt über das SelectOneMenu die Methode usw von deinem Acl Objekt setzt, dann lösche die Zeilen
pm_acl.setMethode(pm_methode);
pm_acl.setGruppe(pm_gruppe);
pm_acl.setBenutzer(pm_benutzer);
aus deiner Store-Methode komplett. Die Werte sind an dieser Stelle doch schon gesetzt und was du dort momentan setzt, sind wieder andere (bzg equals() ) Objekte, als die, die du bereits in der Datenbank hast.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben