5

class Student

public class Student {

private Long id;
private String name;
private String className;
private List<Phone> phones;
    // getter setter
 }

class Phone

public class Phone {

private Long id;
private String number;
   //getter setter
     }

-> mappping file Student.hbm.xml

     <id name="id" type="long" column="id">
        <generator class="native" />
    </id>

    <property name="name" column="name" type="string" />

    <property name="className" column="class_name" type="string" />

    <list name="phones" cascade="all-delete-orphan">
        <key column="student_id"/>
        <list-index column="idx" />
        <one-to-many class="Phone" />
    </list>

-> mapping file Phone.hbm.xml

    <id name="id" type="long" column="id">
        <generator class="native" />
    </id>

    <property name="number" column="number" type="string" />

when i try to update the the phone number (a list), the previous entry is not deleted but the idx(list index) and the foreign key are null and the new entries are marked with the correct idx and foreign key!!The other data (not a list) is updated completely fine. Here I get the class object from the database, modify that and pass the object to saveorupdate(), but didn't help. Been trying this so long.

Code to read and update:

      private void readAndUpdateStudent() {
       Student student = null;
       Session session = HibernateUtil.getSessionFactory().openSession();
       String name = "John";
         try {

        String queryString = "from Student student where student.name =:name";
        Query query = session.createQuery(queryString);
        query.setString("name", name);
        student = (Student) query.uniqueResult();
        System.out.println(student.getName());
        student.setName("Mary");
        List<Phone> phones = new ArrayList<Phone>();
        phones.add(new Phone("555555")); //here if I SET rather adding, the already existing values, update is done accordingly 
        phones.add(new Phone("789789"));//but when I use the list as a string type(instead of Phone Type), adding a new 0bject deletes the previous 
        student.setPhones(phones);//entries and adds new list on its own  but not in the case of user defined type.

    } catch (Exception e) {     
        e.printStackTrace();
        if (session != null) {

            session.close();

        }

    }finally{

        session.close();
        updateStudent(student);
    }

}
private void updateStudent(Student student) {

    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;

    try {
        tx = session.beginTransaction();
        session.saveOrUpdate(student);
        tx.commit();
    } catch (HibernateException e) {
        if (tx != null)
            tx.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
}

enter image description here

Cœur
  • 37,241
  • 25
  • 195
  • 267
gursahib.singh.sahni
  • 1,559
  • 3
  • 26
  • 51
  • Do you try to update a single phone number (e.g. changing the number through the setter) or do you try to change the list of phone numbers of a student? I suspect you're changing the list. – Raffaele Rossi Dec 17 '13 at 16:16
  • am using the setter to set a new list in it like `student.setPhones(phones)` , where phones is the new list – gursahib.singh.sahni Dec 17 '13 at 16:57
  • @anonymous Show your code for updation of Phone. – RAS Dec 18 '13 at 06:38
  • @RaffaeleRossi sir just now i changed the list data rather creating a new list or adding a new list object, and hibernate deletes and updates them accordingly but when i add a new list or create a new object it repeats the same old story. Hope i made myself clear. – gursahib.singh.sahni Dec 18 '13 at 07:01
  • @RAS just now i changed the Phone type to list of string and hibernate is managing all the delete and update operations itself but when the list is user defined type. I have to update and delete on my own. Why is this so? – gursahib.singh.sahni Dec 18 '13 at 07:05
  • @anonymous I'm not able to understand your problem. Can you please show your code business logic? – RAS Dec 18 '13 at 07:11
  • @RAS sir i have updated the question, have a look at it. – gursahib.singh.sahni Dec 18 '13 at 07:22

2 Answers2

2

I notice this is a bit old now, but FWIW, the other answer is right, you shouldn't ever set a new collection on a persistent entity retrieved by hibernate as this will create orphans as it has in your case.

Hibernate proxies the entity so it can manage updates to the database (what fields have changed etc) for the entity's properties. So when you retrieve the entity, and set a new list, hibernate looses the ability to track changes for what used to be in that list. Therefore you should update the existing List as was pointed out, so orphans get removed on update. You can also use clear().

List<Phone> phones = student.getPhones();
phones.clear();
phones.add(new Phone("555555"));
phones.add(new Phone("789789"));
session.saveOrUpdate(student);

If you want to avoid duplicates try a Set rather than a list, and implement hashCode() and equals() on the Phone class, for example, it might make sense to check check equality on phone.number.

Hope this helps :)

waltron
  • 131
  • 9
0

If you want to update a list of phones, you shouldn't do

    List<Phone> phones = new ArrayList<Phone>();
    phones.add(new Phone("555555"));
    phones.add(new Phone("789789"));
    student.setPhones(phones);

The above code doesn't update the list of phones, but create a brand new one. To update a list of phones, you should retrieve the old lists and update its entries:

    List<Phone> phones = student.getPhones();
    phones.get(0).setNumber("666666");
    phones.get(1).setNumber("888888");
    session.saveOrUpdate(student);
Raffaele Rossi
  • 1,079
  • 5
  • 11
  • but when i use built in type of list, hibernate handles all the deletion and update itself. What's wrong with the user defined data types? I HAVE TO ALL THIS MANUALLY !? – gursahib.singh.sahni Dec 18 '13 at 12:22
  • The difference is that Phone is an entity while String is just a primitive type and so they are handled differently – Raffaele Rossi Dec 18 '13 at 13:25