Niepoprawna edycja użytkownika w p:dataTable za pomocą p:dialog - JSF i Primefaces

0

Witam
Chcę napisać coś takiego, że wybierając z menu strone pt. "editPage.xhtml" wyswietli sie na niej cala lista uzytkowników pobranych z bazy danych (JDBC). Kazdy wiersz zawiera przycisk "Edytuj" - czyli kazdy user ma swoj przycisk edycji mowiac inaczej. Mój problem polega na tym, że gdy wybieram Edytuj np. na 3 użytkowniku, edytuje sie zawsze ten ostatni z listy. Co nie wybiore zawsze on jest "celem" edycji.
Obiekt DAO przetestowałem na jakiejś prostej klasie w mainie i sam w sobie działa dobrze.

Oto kody strony i ziarenka:

editPage.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui" xmlns:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Edit users from the list</title>
</h:head>

<h:body>
    <ui:composition template="template.xhtml">
        <ui:define name="content">
            <h:form>
                <p:dataTable value="#{userList.userListToDisplay}" var="user">
                    <p:column headerText="ID:">
                        <h:outputText value="#{user.id}"/>
                    </p:column>
                    <p:column headerText="Imie:">
                        <h:outputText value="#{user.imie}"/>
                    </p:column>
                    <p:column headerText="Nazwisko:">
                        <h:outputText value="#{user.nazwisko}"/>
                    </p:column>
                    <p:column>
                        <p:commandButton value="Edit mode" onclick="PF('editDialog').show();" style="height: 40px;"/>
                        <p:dialog widgetVar="editDialog" effect="slide" style="opacity: 0.90; height: 80px;  width:60%; margin-left: 20%;">
                                <div style="text-align: center; background-color: yellowgreen; width: 100%; border: 2px solid orange; border-radius: 5px;">
                                    <h:outputText value="Imie:"/>
                                    <p:inputText value="#{userList.imie}"/>
                                    <h:outputText value="Nazwisko:"/>
                                    <p:inputText value="#{userList.nazwisko}"/><br/>
                                    <p:commandButton value="Accept" onclick="PF('editDialog').hide(); location.refresh();" action="#{userList.acceptEditedUser(user)}"/>
                                </div>
                        </p:dialog>
                    </p:column>
                </p:dataTable>
            </h:form>
        </ui:define>
    </ui:composition>
</h:body>

</html>

I jeszcze kod ziarenka, troszkę okrojony, żeby ograniczyć wprowadzanie chaosu dla waszych oczu :P


@ManagedBean(name = "userList")
@RequestScoped
public class UserListBean {

    private List<User> userListToDisplay;
    private UserDAO userDAO = new UserDAO();

    private String imie;
    private String nazwisko;

    public UserListBean(){
        this.userDAO.getConnection();
        this.userListToDisplay = this.userDAO.getUsers();
        this.userDAO.closeConnection();
    }

    public String acceptEditedUser(User user){
        this.userDAO.getConnection();
        userDAO.updateUserById(user.getId(), this.imie, this.nazwisko);
        userListToDisplay = this.userDAO.getUsers();
        this.userDAO.closeConnection();
        return null;
    }


    public List<User> getUserListToDisplay() {
        return userListToDisplay;
    }

    public String getImie() {
        return imie;
    }

    public void setImie(String imie) {
        this.imie = imie;
    }

    public String getNazwisko() {
        return nazwisko;
    }

    public void setNazwisko(String nazwisko) {
        this.nazwisko = nazwisko;
    }
}
 

Mam wrażenie jakby p:dialog tworzył się tak jakby tylko raz, na samym końcu przez co zawsze zapamiętuje tego ostatnio dodanego do p:datatable usera.

Potrafi ktoś pomóc? nie mogę sobię z tym poradzić, a znają życie błąd jakiś easy :)
Wcześniej próbowałem też zamiast p:dialog użyc p:notoficationBar, ale wtedy to wgl była klapa dopiero

pozdrawiam!

0

@NoZi bean nosi nazwe UserListBean bo tworzony był, kiedy robiłem stronę która ma tylko wyswietlić tabelę z użytkownikami, potem dodalem kolejna ktora wyswietla tabele, ale jeszcze z możliwościa edycji, i jeszcze jedna strone również z tabelą ale z przyciskiem usun :P Taki prosty CRUD, z którym później chce kombinować. Wiem ze wszystko mozna rownie dobrze umiescic na 1 stronie, ale głównie chciałem najzwyczajniej poćwiczyć ;)

Wszystkie strony podpiąłem pod jednego beana bo defacto robią prawie to samo, maja tylko dodatkowe metody do usuwania, edycji itd. Nie wiem czy to dobrze ze tak zrobilem, bo co racja zasada jednej odpowiedzialności może być złamana, chociaż bean odpowiada za operacje na tabeli z listą użytkowników, więc może jednak nie jest złamana.. :D

Zastanawiam się czy nie powinienem gdzieś tu użyc CDI, ale nigdy o nim nie czytałem, a tym bardziej nie używałem. Nie wiem za bardzo na czym to polega.

pola "imie" i "nazwisko" odpowiadają za ten formularz od edycji użytkownika. Po akceptacji edycji uzytkownika te pola mają wartosc z formularza. I one właśnie zamieniaja sie z rekordami w bazie danych. (uzytkownika szukam po ID bo jest dla każdego indywidualne)

Kod pełnego, nieokrojonego beana:

package com.maciej.beans;

import com.maciej.dto.User;
import com.maciej.dto.UserDAO;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import java.util.List;

@ManagedBean(name = "userList")
@RequestScoped
public class UserListBean {

    private List<User> userListToDisplay;
    private final UserDAO userDAO = new UserDAO();

    private String imie;
    private String nazwisko;

    public UserListBean(){
        this.userDAO.getConnection();
        this.userListToDisplay = this.userDAO.getUsers();
        this.userDAO.closeConnection();
    }

    public String removeUserFromList(User user){
        this.userDAO.getConnection();
        this.userDAO.deleteUser(user);
        this.userListToDisplay = this.userDAO.getUsers();
        this.userDAO.closeConnection();
        return null;
    }

    public String acceptEditedUser(User user){
        this.userDAO.getConnection();
        userDAO.updateUserById(user.getId(), this.imie, this.nazwisko);
        userListToDisplay = this.userDAO.getUsers();
        this.userDAO.closeConnection();
        return null;
    }





    public List<User> getUserListToDisplay() {
        return userListToDisplay;
    }

    public String getImie() {
        return imie;
    }

    public void setImie(String imie) {
        this.imie = imie;
    }

    public String getNazwisko() {
        return nazwisko;
    }

    public void setNazwisko(String nazwisko) {
        this.nazwisko = nazwisko;
    }
}

Kod UserDAO:

 
package com.maciej.dto;

import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class UserDAO {

    private final String DRIVER = "com.mysql.jdbc.Driver";
    private final String USERNAME = "UZYTKOWNIK";
    private final String USERPASS = "HASLO";
    private final String DB_URL = "jdbc:mysql://localhost:3306/test";

    private Connection connection;
    private Statement statement;


    public UserDAO() {
    }

    public boolean getConnection() {
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(DB_URL, USERNAME, USERPASS);
            System.out.println("Connection accepted.");
            return true;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean closeConnection(){
        try {
            connection.close();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    public List<User> getUsers(){
        List<User> userList = new ArrayList<User>();
        try {
            statement = connection.createStatement();
            ResultSet usersResultSet = statement.executeQuery("SELECT * FROM users");
            while(usersResultSet.next()){
                userList.add(
                        new User(usersResultSet.getInt("id"), usersResultSet.getString("imie"), usersResultSet.getString("nazwisko"))
                );
            }
            return userList;
        } catch (SQLException e) {
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

     /**
     * true if added, false if returns an error
     */
    public boolean addUser(String imie, String nazwisko){
        if(connection != null){
            try {                                                           //INSERT INTO users (id, imie, nazwisko) VALUES (NULL, ?, ?)
                PreparedStatement prepstat = connection.prepareStatement("INSERT INTO users VALUES (NULL, ?, ?)");
                prepstat.setString(1, imie);
                prepstat.setString(2, nazwisko);
                prepstat.executeUpdate();
                return true;
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
        }else{
            return false;
        }
    }

    public boolean deleteUser(User user){
        if(connection != null){
            try {
                PreparedStatement prepstat = connection.prepareStatement("DELETE FROM users WHERE id=? AND imie=? AND nazwisko=? limit 1");
                prepstat.setInt(1, user.getId());
                prepstat.setString(2, user.getImie());
                prepstat.setString(3, user.getNazwisko());
                prepstat.executeUpdate();
                return true;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
    /**
     * User is indetified only by individual ID.
    */
    public boolean updateUserById(int userID, String newName, String newLastname){
        if(connection != null){
            try {
                PreparedStatement prepstat = connection.prepareStatement("UPDATE users SET imie=?, nazwisko=? WHERE id=?;");
                prepstat.setString(1, newName);
                prepstat.setString(2, newLastname);
                prepstat.setInt(3, userID);
                prepstat.executeUpdate();
                return true;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

}

0

Witam pewności nie mam że podaje dobre rozwiązanie ale tylko takie mi przyszło na myśl

Dodaj do UserListBean pole

private User selectedUser; (gety i sety ! )

Zmien przycisk w tabeli na

 <p:commandButton value="Edit mode" onclick="PF('editDialog').show();" style="height: 40px;">
    <f:setPropertyActionListener value="user" target="#{userList.selectedUser}" />
 </p:commandButton>
 

Następnie

 
                                    <h:outputText value="Imie:"/>
                                    <p:inputText value="#{userList.selectedUser.imie}"/>
                                    <h:outputText value="Nazwisko:"/>
                                    <p:inputText value="#{userList.selectedUser.nazwisko}"/><br/>
                                    <p:commandButton value="Accept" onclick="PF('editDialog').hide(); location.refresh();" action="#{userList.acceptEditedUser()}"/>

w metodzie acceptEditedUser obsłuż sobie zapisywanie selectedUser

1 użytkowników online, w tym zalogowanych: 0, gości: 1