1

I have an object mapped with hibernate that contains an id and a collection. At some point in time when the object contains items in it's collection I want to do obj.setCollection(new ArrayList()) and have it delete the items from the database that were previously in the collection. If anyone could assist it would be much appreciated. Code to illustrate problem:

ORM: Foo 1-* Bar and Bar 1-1 Foo

class Foo {
    Long id;
    List<Bar> bars;

    //getters & setters
}

<hibernate-mapping>
    <class name="domain.Foo" table="Foos">
        <id name="id" type="long" column="id">
            <generator class="native" />
        </id>
        <list name="bars" lazy="true" cascade="all">
            <key column="FOO_ID" not-null="true" />
            <index column="SEQUENCE" />
            <one-to-many class="domain.Bar" />
        </list>     
    </class>    
</hibernate-mapping>

@Entity
@Table(name="Bars")
public class Bar {
    private Long id;
    private Foo foo;
    private String name;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="ID")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ManyToOne
    @JoinColumn(name="FOO_ID", insertable=false, updatable=false)
    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

    @Column(name="NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
James
  • 1,720
  • 5
  • 29
  • 50

4 Answers4

3

What you probably want to do is :

obj.getCollection().clear();
Guillaume
  • 18,494
  • 8
  • 53
  • 74
  • I've just tried this and it doesn't seem to make any difference :-\ `foo.getBars().clear(); fooDao.makePersistent(foo);` – James Jan 24 '11 at 12:18
3

You should never replace a collection manged by Hibernate (for example if you have an object containing a collection, and this object is loaded by Hibernate) by an new collection!

Always use the collection methods (add, remove, clear, ...) to manipulate the method.

Ralph
  • 118,862
  • 56
  • 287
  • 383
1

If you want Hibernate to remove objects from the database when you remove them from the collection, you need to configure delete-orphan option for that collection:

<list name="bars" lazy="true" cascade="all-delete-orphan">

Though in this case you cannot replace the collection, you need to use collection methods instead (see Ralph's answer and remove collection with delete-orphan not work with null assignment? :()

Community
  • 1
  • 1
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • Just to add another note, field level access seems to be required due to the custom methods. Problem solved, thanks very much :) – James Jan 25 '11 at 10:40
0

Or something like this (I like to encapsulate fields):

class Foo {
    Long id;
    List<Bar> bars = new ArrayList<Bar>();

    ...

    public List<Bar> getBars() {
        return new ArrayList<Bar>(bars);
    }

    public void setBars(List<Bar> newBars) {
        bars.clear();
        bars.addAll(newBars);
    }

    public void addBar(Bar bar) {
        bars.add(bar);
    }

    public void removeBar(Bar bar) {
        bars.remove(bar);
    }
}
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
  • 1
    I think your getter should at least return an immutable list. Else the caller will be quite surprised that its modifications to the list are not reflected in the foo object. It's probably a matter of taste, but I would prefer not to have too much encapsulation and remove the setBars() method. getBars().add() is as readable than addBar() ... But that's only my opinion ... – Guillaume Jan 24 '11 at 10:16