I solved the problem. The collection filled with data by Hibernate
was not sorted. After adding order-by into the set definition in my
Party.hbm.xml all works fine:
<class name="net.expertys.model.Party" table="Party">
<id name="partyID" column="partyID" type="long">
<generator class="increment"/>
</id>
<set name="addresses" inverse="true" cascade="all,delete-orphan"
order-by="nameAddressID">
<key column="partyID"/>
<one-to-many class="net.expertys.model.NameAddress"/>
</set>
</class>
I use the database id nameAddressID to identify the repeater rows, no
extra ids are necessary.
Barbara
On 8 Jun, 2007, at 10:46 pm, Barbara Slupik wrote:
Hello
I am trying to add a row in a CForms repeater but the new row
replaces some of the old data in the collection.
I am using Cocoon-2.1.10 with Hibernate-3.2, Spring-2.0.4 and
MySQL-5.0.37. The repeater rows are loaded from the database and
displayed correctly on the screen. When I try to add a new row
sometimes it works and after the form is submited my collection
contains all rows from the repeater. But most times the last object
in the original collection gets replaced by the new repeater row
and a null object is added to the collection. I think that the
problem might be with the row id. I was experimenting with it but
cannot make it work.
Below are some parts of the code. Please can anyone offer some help
or suggestions for how to make it work.
Barbara
Beans
==========
// Party is the main item on the form
public class Party {
...
private Long partyID;
private Collection addresses=new ArrayList();
...
public void setAddresses(Collection addresses) {
this.addresses=addresses;
int i=0;
Iterator it=addresses.iterator();
while (it.hasNext()) {
NameAddress address=(NameAddress)it.next();
address.setId(i);
i=i+1;
}
}
public void addAddress(NameAddress address) {
//address.setId(addresses.size());
addresses.add(address);
address.setParty(this);
}
}
// NameAddress are the items which appear in the repeater,
nameAddressID is the id from the database
public class NameAddress {
private int id;
private Long nameAddressID;
private Long partyID;
...
}
Binding
===========
<fb:repeater id="addresses" parent-path="." row-path="addresses">
<fb:identity>
<fb:value id="id" path="id"/>
<!--<fb:value id="nameAddressID" path="nameAddressID"/>-->
</fb:identity>
<!-- executed on updates AND right after the insert -->
<fb:on-bind>
<fb:javascript id="id" path="id" direction="save">
<fb:save-form>
if (widget.getValue()==null) {
var form = widget.getForm();
var count =
form.getAttribute("addressCounter");
jxpathPointer.setValue(count);
form.setAttribute("addressCounter", count+1);
}
</fb:save-form>
</fb:javascript>
<!--<fb:value id="nameAddressID" path="nameAddressID"/>-->
...
</fb:on-bind>
<!-- executed in case a row has been deleted -->
<fb:on-delete-row>
<fb:delete-node/>
</fb:on-delete-row>
<!-- executed in case a new row has been added -->
<fb:on-insert-row>
<fb:insert-bean classname="net.expertys.model.NameAddress"
addmethod="addAddress"/>
</fb:on-insert-row>
</fb:repeater>
...
Flow
=======
function Party() {
getApplication();
var id=cocoon.request.getParameter("id");
var party=application.readParty(new java.lang.Long(id));
var formDefinition=cocoon.parameters["form-defn"];
var formBinding=cocoon.parameters["form-bind"];
var form=new Form(formDefinition);
form.setAttribute("addressCounter",party.getAddresses().size());
form.createBinding(formBinding);
form.load(party);
form.showForm("Party-display");
if (form.isValid) {
if (id==null) {}
else {
form.save(party);
application.saveParty(party);
cocoon.sendPage("Party?id="+id);
}
}
else {cocoon.redirectTo("Parties(1)")};
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]