Odświeżanie asocjajci hibernate w jTable.

0

Witajcie.

Taka oto acosjaja z wykozystaniem hibernata:

@Entity
@Table(name = "CHECKLIST")
@SequenceGenerator(name="PK",sequenceName="GEN_CHECKLIST_ID",allocationSize=1)
public class Checklist implements java.io.Serializable{

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PK")
@Column(name = "ID")        
private int id;
@Column(name = "QUESTION")
private String question;

@JoinColumn(name = "KIND_ID")
@ManyToOne
private Kind kind;

@JoinColumn(name = "PRIORITIES_ID")
@ManyToOne
private Priority priority;

@JoinColumn(name = "AREA_ID")
@ManyToOne
private Area area;

@JoinColumn(name = "STANDARD_ID")
@ManyToOne
private Standard standard;

@Column(name = "COMMENTS")
private String comment;

@JoinColumn(name = "USER_ID")
@ManyToOne
private UserLogin userLogin;

@Column(name = "ADDED")
private Timestamp timestamp;

@Column(name = "ACTIVE")
private boolean active;

Odczyt z bazy danych:

public void refresh(){
Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx=null;
        try{
            session.beginTransaction();
            Query q = session.createQuery("from Checklist");
            List resultList = q.list();
            display(resultList);
            session.getTransaction().commit();
            }
        catch (Exception e) {if (tx!=null) tx.rollback();e.printStackTrace(); }
        finally {session.close();}  
}   

Wyświetlenie w jTable:

private void display(List resultList) {
 Vector<String> tableHeaders = new Vector<String>();
 Vector tableData = new Vector();
 tableHeaders.add("ID:"); 
 tableHeaders.add("Pytanie:");
 tableHeaders.add("Typ:");
 tableHeaders.add("Priorytet:");
 tableHeaders.add("Obszar:");
 tableHeaders.add("Standard:");
 tableHeaders.add("Komentarz:");
 tableHeaders.add("Dodał:");
 tableHeaders.add("Data dodania:");
 tableHeaders.add("Aktywne:");
 
 for(Object o : resultList) {
 Checklist actor = (Checklist)o;
 Vector<Object> oneRow = new Vector<Object>();
 oneRow.add(actor.getId());
 oneRow.add(actor.getQuestion());
 oneRow.add(actor.getKind().getDescription());
 oneRow.add(actor.getPriority().getDescription());
 oneRow.add(actor.getArea().getDescription());
 oneRow.add(actor.getStandard().getDescription());
 oneRow.add(actor.getComment());
 oneRow.add(actor.getUserLogin().getName()+" "+actor.getUserLogin().getSurname());
 oneRow.add(actor.getTimestamp());
 oneRow.add(actor.isActive());
 tableData.add(oneRow);
 }
}

I tutaj wszystko pięknie działa, problem pojawia się przy aktualizacji danych bezpośrednio w jTable. Do tabelki dołożyłem lisenera zmiany danych:

table.getModel().addTableModelListener(new TableModelListener() {
   public void tableChanged(TableModelEvent e){     
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx=null;
    tx = session.beginTransaction();
    try{
        UserLogin l = (UserLogin)session.get(UserLogin.class, userID);       
        Checklist c = (Checklist)session.get(Checklist.class, index); 
       
        int row=table.getSelectedRow();
        
        c.setQuestion(String.valueOf(table.getModel().getValueAt(row, 1)));     
        c.setComment(String.valueOf(table.getModel().getValueAt(row, 6)));
        c.setUserLogin(l);      
        c.setTimestamp(new Timestamp(System.currentTimeMillis()));
        session.update(c);
        tx.commit();
        }
    catch (Exception exp) {if (tx!=null) tx.rollback();exp.printStackTrace(); }
    finally {session.close();} 
     }
 });

I teraz gdy zmieniam dane nie będące w relacji jak np. pytanie wszystko gra. Po zmianie w jtable zostaje to przeniesione do bazy. Problem pojawia się gdy zmieniam dane będące w relacji jak np. UserLogin w bazie wszytko się zmienia jednak w jtable pozostaje bez zmiany. Poptrzebne jest kolejne wywolanie funkcj refresh czyli tak naprwde odczyt z bazy.

Domyślam się że działa po poprawnie ponieważ zmia dokonuje nie w jTable tyko tworząc i sktualizując nowy obiekt UserLogin l = (UserLogin)session.get(UserLogin.class, userID); dlatego jTable nic nie wie o tej zmianie. Czy jest jakis sposób aby wymusić taka aktualizacje, bez pobierania danych z bazy kolejny raz?

0

Ano jest. Kontroler który wywołuje akcje zmiany danych w bazie powinien też poinformować o nich tabelkę.

0

Ok tak też pomyslałem, dodałem funkcje do modelu tebleki:

public void setValueAt(Object value, int row, int col){
             ((Vector) tableData.get(row)).setElementAt(value, col);
             fireTableCellUpdated(row,col);
            }

ale niebardzo mam pomysł gdzie ja wywołać, chciałem dodac ją w

public void tableChanged(TableModelEvent e), 

i wywołac gdy zają zmiany w tablei no ale oczywiście mi się zapętla. Jakaś rada?

0

Taka moja mała - zmienił bym logikę tego. Zrób model Jtable w nowym pliku , implementuj Abstractablemodel
uzupełni odpowiednio i dopisz takie coś fireTableChanged()
to zadziała (wybacz skrót myślowy bo nie mam czasu ani kodu by Ci to pokazać)

0

@Izsk dzięki za rade, tak jak napisałeś zrobiłem. Oddzielna klase dla AbstractTableModel, i użyłem:

fireTableCellUpdated(row,col); fireTableDataChanged();

w modelu tabelki. Funkcja działa niestety nadal brak oczekiwanego razultatu. Może troche to źle wytłumaczyłem. Mam tabele w której jedną z kolumn jest ID użytkownika zmieniającego dane (jest to relacji z inna tabelą). I teraz przy zmianiej wartościw dowolnej komórki z całej tabeli, automatycznie do tej kolumny powinei wskoczyć ID osoby która dokonuje edycji.

Obiekt osoby pobieram tak:

UserLogin l = (UserLogin)session.get(UserLogin.class, userID);  

następnie dodaje do obiektu edytowanego wiersza (wspomniana ralacj) i zapisuje za pośrednictwem hibernata:

Checklist c = (Checklist)session.get(Checklist.class, index);                  
        c.setUserLogin(l)  ;           
        session.update(c);
        tx.commit();

I teraz chodzi o to że w wyświetlanej tabelce (w modelu) nie widać tej zmiany w tej kolumnie z użytkownikiem. Prawdopodobnie dlatego żę nie zmieniam nic bezpośrednio w modelu, jak w przypadku innych pól. I teraz chodzi oto jak wysłać modelowi informace aby zmienił wyświetlany obiekt w tej kolumnie. Myślałem że fireTableDataChanged(); wystarczy no ale niestety.

Chciałem updejtować model (kolumne z ID uzytkownika) tym:

model.setValueAt(l.getName()+" "+l.getSurname(), row, 8);

No ale gdy wstawie to w

public void tableChanged(TableModelEvent e){ 
model.setValueAt(l.getName()+" "+l.getSurname(), row, 8);
   }});

funkcja mi się zapętla i po robocie. SelValue zminie wartość w tabelce -> tableChange wykryje wartoć i tak będą sie wywoływać. Nie mam pomysły jak inaczej moge wywołać te zmiane.

public class MyAbstractTableModel  extends AbstractTableModel {

     private String[] columnNames;
     private Vector data = new Vector();
     
     public MyAbstractTableModel(Vector tableHeaders, Vector tableData){
     this.columnNames=(String[]) tableHeaders.toArray(new String[0]);    
     this.data=tableData;     
     }
     
     @Override
     public int getColumnCount() {
     return columnNames.length;
     }

     @Override
     public int getRowCount() {
     return data.size();
     }

     @Override
     public Object getValueAt(int row, int col) {
     return ((Vector) data.get(row)).get(col);
     }

     public String getColumnName(int col){
     return columnNames[col];
     }
     public Class getColumnClass(int c){
     return getValueAt(0,c).getClass();
     }

     public void setValueAt(Object value, int row, int col){
     System.out.println("setValue z modelu");   
     ((Vector) data.get(row)).setElementAt(value, col);
     fireTableCellUpdated(row,col);
     fireTableDataChanged();
     }
    
     boolean[] canEdit = new boolean[]{
        false,true,true,true,true,true,true,false,false,true
        };
     public boolean isCellEditable(int rowIndex, int columnIndex) {
        return canEdit[columnIndex];
        }

     public void insertData(Object[] values){
     data.add(new Vector());
     for(int i =0; i<values.length; i++){
     ((Vector) data.get(data.size()-1)).add(values[i]);
     }
     fireTableDataChanged();
     }

     public void removeRow(int row){
     data.removeElementAt(row);
     fireTableDataChanged();
     }
  }
0

tak nadal nie mam czasu na to by Ci to dokładnie pokazać i opisacla o co mi chodzi . jak dasz maila to Ci coś wyślę - na postawie tego zrobisz to co Ci jest potrzebne :)

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