Hibernate, aktualizacja kolekja w asocjaji ManyToMany

0

Hej,

Napisalem taką asocjaje:

Klasa AREA

@Entity
@Table(name = "AREA")
@SequenceGenerator(name="PK",sequenceName="GEN_AREA_ID",allocationSize=1)
public class Area implements Serializable{
 @Id
 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PK")
 @Column(name = "ID")     
 int id;
 
 @Version                                                                  
 @Column(name = "VERSION")
 private int version;
 
 @Column(name = "DESCRIPTION")
 String description;
 @Column(name = "ACTIVE")
 boolean active;

 @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
 @JoinTable(name="QUESTIONS_AREAS", 
           joinColumns={@JoinColumn(name="AREAS_ID")},
           inverseJoinColumns={@JoinColumn(name="QUESTIONS_ID")})
 private Set<Question> questions = new HashSet<Question>(0);

Klasa QUESTION

@Entity
@Table(name = "QUESTIONS")
@SequenceGenerator(name="PK",sequenceName="GEN_QUESTIONS_ID",allocationSize=1)
public class Question implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PK")
@Column(name = "ID")     
private int id;

@Version                                                                   
@Column(name = "VERSION")
private int version;

@Column(name = "DESCRIPTION")
private String description;

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

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name="QUESTIONS_AREAS", 
           joinColumns={@JoinColumn(name="QUESTIONS_ID")},
           inverseJoinColumns={@JoinColumn(name="AREAS_ID")})
private Set<Area> areas = new HashSet<Area>(0);

Chce do konkretnego obiektu Question przypisac wiele obiektów Area, w tym celu zrobiłe sobie tabelke która wyświetla listę dostępnych obiektów Area z dodtakową kolumną w której umieściełem CheckBoxa. Klikając na checboxa w danym wierszu (zaptaszająć) chce aby obiekt Area został dodany do kolekcji obiektu Question. W tym celu do tabelki dodałem lisenera który wywołuje:

areaTable.getModel().addTableModelListener(new TableModelListener(){       
   public void tableChanged(TableModelEvent e){              
       try {
            Area a = DAO.AreaDAO.getAreaById(areaIndex);
            DAO.AreaDAO.addQuestionByID(a, question);
           }catch (IOException ex) {Logger.getLogger(QuestionsMargeFrame.class.getName()).log(Level.SEVERE, null, ex);}                 
   }});  

Metoda zmian w kolekcji:

  public static void addQuestionByID(Area a, Question q) throws IOException{
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx=null;
    try{
         tx = session.beginTransaction();
         a.getQuestions().add(q);
         session.saveOrUpdate(a);
         tx.commit();
        }
    catch (Exception e) {if (tx!=null) tx.rollback();e.printStackTrace();Log.setLog(e.toString()); }
    finally {session.close();}
    }   

I wszystko działa dla pierwszych 8 dodanych obiektów, następnie otrzymuje komunikat:

A different object with the same identifier value was already associated with the session : [clases.Question#28]

To moje początki w hibernate i sprawa chyba mnie przerosla, może macie jakiś pomysł.

1

Na oko:
Masz kolekcje Questionów które nie są powiązane z sesją hibernate, tzn są oderwanymi obiektami. Niemniej dodanie takiego obiektu do obiektu encyjnego wyciągniętego z bazy, przy aktywnej sesji i z kaskadą powoduje oczywiście że w bazie pojawi się odpowiednia aktualizacja. Niemniej twój obiekt Question nadal nie jest w zaden sposób zsynchronizowany z bazą. W efekcie twój lokalny obiekt ma pustego Seta z Area a w bazie juz są jakieś wpisy w tym secie. Jak wyciągniesz Question z danym ID z bazy to będzie miał tam jakieś Area. Problem pojawia się dlatego że do Area dodajesz ten "stary" obiekt a potem próbujesz zapisać w bazie i hibernate widzi że co prawda ID tego obiektu się zgadza z tym co jest w bazie, ale ten obiekt nie jest zgodny z tym co jest w bazie.

0

Ok, mój błąd jak zwykle miałes racje, w ten sposób dziła:

public static void addQuestionByID(int areaIndex, int questionIndex) throws IOException{
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx=null;
    try{
         tx = session.beginTransaction();
        
         Area a = (Area)session.get(Area.class, areaIndex);  
         Question q = (Question)session.get(Question.class, questionIndex); 
         
         a.getQuestions().add(q);        
         session.update(a);

         tx.commit();
        }
    catch (Exception e) {if (tx!=null) tx.rollback();e.printStackTrace();Log.setLog(e.toString()); }
    finally {session.close();}
    }      

Dzieki za pomoc.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.