2012-04-05 8 views
4

Ich entwickle eine Java-Webanwendung mit Hibernate und JSF/Primefaces. bekomme manchmal Fehler wieRuhezustand, Sitzung, Lazyloading

1) ein Objekt mit demselben Bezeichner ist bereits Sitzung zugeordnet.

2) Fehler beim Laden der faulen Initialisierung *, keine Sitzung vorhanden oder Sitzung ist bereits geschlossen.

Ich weiß, dass dies auf falsche Codierung in meiner App zurückzuführen ist. Dies ist die Art, wie ich aap mache:

Wenn ein Benutzer eine Seite anfordert (sei es eine Liste von Mitarbeitern). der Benutzer wird die Mitarbeiterlistenseite (empployeeList.xhtml) EmployeeListMBean ist die verwaltete Bean für diese Seite. in der verwalteten Bean im Konstruktor, Aufruf einer Methode populateEmployees(). populateEmployee() verwendet die EmployeeDao-Methode getAllEmployee(), um GetAllemployees zu erhalten.

Mitarbeiter Klasse geht hier:

@Entity 
@Table(name = "Employee") 
@NamedQueries({ 
    @NamedQuery(name = "Employee.getAllEmployee", query = "from Employee"), 
    @NamedQuery(name = "Employee.findEmployeeByFirstName", query = "from Employee where firstName = :firstName"), 
    @NamedQuery(name = "Employee.findEmployeeByLastName", query = "from Employee where lastName = :lastName"), 
    @NamedQuery(name = "Employee.findEmployeeByMiddleName", query = "from Employee where middleName = :middleName"), 
    @NamedQuery(name = "Employee.findEmployeeByOffice", query = "from Employee where office.id = :officeId") 
}) 
public class Employee implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "EID") 
    private long id; 
    @Column(name = "FIRST_NAME") 
    private String firstName; 
    @Column(name = "LAST_NAME") 
    private String lastName; 
    @Column(name = "GENDER") 
    private String gender; 
    @Column(name = "DOB") 
    @Temporal(javax.persistence.TemporalType.DATE) 
    private Date dateOfBirth; 
    @Column(name = "DOH") 
    @Temporal(javax.persistence.TemporalType.DATE) 
    private Date dateOfHire; 
    @ManyToOne(cascade= CascadeType.ALL) 
    private Office office; 
    @OneToOne(cascade = CascadeType.ALL) 
    private ResidenceAddress residence; 
    @OneToMany 
    private List<Project> projects; 

    //getters and setters 

} 

hier ist mein EmployeeDao:

public class EmployeeDao implements Serializable{ 
    private SessionFactory factory; 
    private Session session; 
    public void addEmployee(Employee employee){ 
     factory = HibernateUtil.getSessionFactory(); 
     session = factory.openSession(); 
     session.beginTransaction(); 
     session.save(employee); 
     session.getTransaction.commit();   
    } 
    public List<Employee> getAllEmployee(){ 
     factory = HibernateUtil.getSessionFactory(); 
     session = factory.openSession(); 
     session.beginTransaction(); 
     List<Employee> cities = session.getNamedQuery("Employee.getAllEmployee").list(); 
     session.close(); 
     return cities; 
    } 

    public Employee getEmployeeByEmployeeId(long employeeId){ 
     factory = HibernateUtil.getSessionFactory(); 
     session = factory.openSession(); 
     session.beginTransaction(); 
     Employee employee = (Employee) session.get(Employee.class, employeeId); 
     session.close(); 
     return employee; 
    }  
} 

Frage 1) hier in den Methoden, die ich die Sitzung am Schließen und dann das Ergebnis wieder zurück zu bewirtschafteten Bohnen. so in der Mitarbeiter-Listing-Seite die Tabelle Liste Name dob dateOfHire. und ich habe eine detailliertere Ansicht. Wenn ich auf diese Schaltfläche klicke, möchte ich alle Projekte des ausgewählten Mitarbeiters anzeigen, die mit den gleichen verwalteten Beans arbeiten, aber es gibt mir einen Fehler (2), es ist nicht möglich, Lazyload auszuführen, keine Sitzung oder Sitzung ist bereits geschlossen. Wenn ich die Sitzung im getemployeeMethod von dao geöffnet halte, kann das zu einem Speicherverlustproblem oder einem anderen Problem führen. ist es so? Ich habe auch versucht, faul und eifrig zu laden. Bitte geben Sie mir eine klare Vorstellung, wann/wie Sie diese Art des Abrufens verwenden. Wie kann ich das lösen? kann ich mich für Filter oder Facelisten entscheiden, um das zu lösen?

Frage 2) Wenn ich versuche, ein Projekt eines Mitarbeiters zu bearbeiten, und aktualisieren mit session.saveorupadte(), merge(), flush(), bekomme einen Fehler wie folgt, "ein Objekt mit der gleichen Kennung ist bereits mit der Sitzung verbunden " Wie kann ich das lösen?

Frage 3) Ich weiß, dass Sessionsfactory ist ressourcenverbrauchend. Daher reicht nur eine einzige Instanz für eine App aus. aber was ist mit Sitzung? für einen einzelnen Benutzer der App, nur eine Sitzung benötigt? Bitte sagen Sie mir eine gute Strategie für die Entwicklung einer solchen App.

Sie alles, was ich denke, Ihre erste Frage die Antwort :)

+0

Dies ist wirklich mehrere Fragen. Sie können eine bessere Antwort erhalten, wenn Sie sich auf ein Problem pro Frage konzentrieren. –

Antwort

0

Wie in der anderen Antwort erwähnt, sollten Sie commiting die Transaktionen, die Sie gestartet haben, sein. Die Transaktionen werden nicht benötigt, während Sie die Daten lesen.

Frage 1: Lazy Loading.

Sie müssen lazy loadprojects, so dass sie sich frei in der Ansicht verwendet werden kann. Um das zu tun, ändern Sie den Code wie unten,

@OneToMany(fetch=FetchType.LAZY) 
private List<Project> projects; 

Frage 2: ein Objekt mit demselben Bezeichner ist bereits vorhanden sein.

Debuggen Sie und finden Sie heraus, was id des Objekts ist, das Sie speichern werden. Ich kann hier nicht viel helfen ohne einen Stacktrace deines Fehlers.

Frage 3: Sitzung und Sessionfactory.

Hier ist der Unterschied zwischen den beiden aus dieser article.

Session ist überwintert Konzept eines einzigen Datenspeicher und ist THREAD so dass viele Threads es gleichzeitig und Anforderung für Sitzungen und unveränderliche Cache von kompilierten Mappings für eine einzelne Datenbank zugreifen können. Eine SessionFactory wird normalerweise nur einmal beim Start erstellt. SessionFactory sollte in eine Art Singleton eingebettet sein, damit in einem Anwendungscode leicht darauf zugegriffen werden kann.

Sitzung ist ein leichtgewichtiges und nicht threadsicheres Objekt (Nein, Sie können es nicht zwischen Threads teilen), das eine einzelne Arbeitseinheit mit der Datenbank darstellt. Sitzungen werden von einer SessionFactory geöffnet und dann geschlossen, wenn alle Arbeiten abgeschlossen sind. Sitzung ist die primäre Schnittstelle für den Persistenzdienst. Eine Sitzung erhält eine Datenbankverbindung langsam (d. H. Nur wenn erforderlich). Um das Erstellen zu vieler Sitzungen zu vermeiden, kann die ThreadLocal-Klasse wie unten gezeigt verwendet werden, um die aktuelle Sitzung abzurufen, unabhängig davon, wie oft Sie die Methode currentSession() aufrufen.

in Ihrem Code Also, sollten Sie eine lokale Variable für session erstellen und es jedes Mal, wenn Sie die Methode schließen schließen.

0

deinnkening ist, dass Sie in jeder Nutzung verpflichten Ihre Sitzung nicht. Ich meine in getAllEmployee und getEmployeeByEmployeeId Methoden, die Sie Ihre Transaktion nicht begehen. Sie können hinzufügen, session.getTransaction.commit(); Ich bin mir nicht sicher, aber Ihr erstes Problem kann die zweite verursachen, weil die Transaktion nicht festlegt. Für die gute Strategie mit der Sitzung können Sie this suchen.

+0

Okay, ich werde das versuchen, indem ich eine commit int schlauch Methoden hinzufüge. Ich bin mir aber nicht sicher, warum Commit einzubeziehen ist, wenn wir nur Objekte aus der Datenbank lesen und keine Änderungen in der Datenbank vornehmen. In der addEmployee-Methode habe ich festgeschrieben, da es einen Schreibvorgang gibt. Habe ich nicht recht, ich meine mein Verständnis von commit()? – amFroz

+0

In meinem Verständnis beendet commit einfach die Datenbanktransaktion. 'Durch die Übergabe einer Datenbanktransaktion wird eine Sitzung von der JDBC-Verbindung getrennt und die Verbindung zum Pool zurückgegeben.' Sie können den ganzen Artikel hier lesen http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html – mbaydar

+0

Okay. Vielen Dank. Ich werde das versuchen. Gibt es ein Problem beim Öffnen der Sitzung und alle in der Ansicht? Ich meine in meiner App, kann ich Sitzung in den Managed Beans öffnen? wenn nein, denke ich, dass es mein Objektproblem mit demselben Bezeichnerproblem lösen kann (Frage 2). – amFroz

Verwandte Themen