Hello again.

Well I guess I'll deal with scenario (1) for now. The deal is that when you
create a new Application you at least have to assign streetSection1. You can
also assign streetSection2 and place but they are not obligatory. (You never
create NEW StreetSections or Places ...) This is what I have.:

@Entity
public class Application
...
private StreetSection streetSection1;
private StreetSection streetSection2;
private Place place;
...
public Application()
{
  this.streetSection1 = new StreetSection();
  this.streetSection2 = new StreetSection();
  this.place = new Place();
}
...
@ManyToOne
@JoinColumn(name="idStreetSection1", nullable=false)
public StreetSection getStreetSection1() ...

@ManyToOne
@JoinColumn(name="idStreetSection2", nullable=false)
public StreetSection getStreetSection2() ...

@ManyToOne
@JoinColumn(name="idPLace", nullable=false)
public Place getPlace() ...

In the jsp I have the following:

<form:hidden path="streetSection1" id="streetSection1" />
<form:hidden path="streetSection2" id="streetSection2" />
<form:hidden path="place" id="place" />

I used to have it as 'streetSection1.id', 'streetSection2.id', etc. and had
to put an <c:if> to check if streetSecion1.id was null or not. but now I
have implemented getAsText() in the StreetSectionPropertyEditor and
PlacePropertyEditor (I already had setAsText()):

public void setAsText(String id)
{
  StreetSection streetSection = streetSectionManager.get(new Long(id));
  setValue(streetSection);
}

public String getAsText()
{
  StreetSection streetSection = (StreetSection) getValue();
  if (streetSection == null) return "";
  else return (streetSection.getId() == null) ? "" :
streetSection.getId().toString();
}

PlacePropertyEditor is exactly the same. getAsText() returns the id of the
existing StreetSection or Place, when loading an existing Application. If
it's a new Application (and thus a new StreetSection and Place) it returns
an empty string.

And this is my ApplicationFormController initBinder():

protected void initBinder()
{
  StreetSectionPropertyEditor sspe = new StreetSectionPropertyEditor();
  sspe.setStreetSectionManager(streetSectionManager); 
  binder.registerCustomEditor(StreetSection.class, "streetSection1", sspe);
  binder.registerCustomEditor(StreetSection.class, "streetSection2", sspe);
                
  PlacePropertyEditor ppe = new PLacePropertyEditor();
  ppe.setPlaceManager(placeManager); 
  binder.registerCustomEditor(Place.class, "place", ppe);
}

This works for existing Applications. And it also works when creating a new
Application if I fill in all three fields - streetSection1, streetSection2
and place. But when I create a new Application, and only assign
streetSection1 or streetSection1 and streetSection2 I get this error:

object references an unsaved transient instance - save the transient
instance before flushing: com.myco.myapp.model.Place; nested exception is
org.hibernate.TransientObjectException: object references an unsaved
transient instance - save the transient instance before flushing:
com.myco.myapp.model.Place

Whew! And that's just scenario (1). I think I must be overlooking something
simple, something that's implemented for StreetSection that is not
implemented for Place. Since it only craps out when I send a null Place, it
must be that it's not handling 'null' well. But in the jsp when I don't
assign a Place I make sure the 'place' hidden is disabled (null) before
submitting. Interestingly, setTextAs() is NOT called when a null value is
sent. I guess this is correct. But it must mean that the PropertyEditor is
not the problem because it's not even making it that far ... 

As far as scenario (2) goes I am looking into it ... unfortunately it
doesn't seem a trivial thing to do. I thought that the <spring:bind> tag had
been surpassed by the <form> tags for binding lists. In fact for simpler
objects I am using <form:select>. But for the EstablishmentContainer objects
I am going to have to add a 'row' to an html table with some <hidden> and
text tags for each EstablishmentContainer added, and somehow get a
PropertyEditor to assign them correctly. I will look into using the <bind>
tag and a PropertyEditor. It's not going to be easy I think, but preferable
to picking out all of the values from the request, manually instantiating
and populating every EstablishmentContainer object and adding it to the
List.

I'll keep you posted!

Bob

 



or objects

Mike Horwitz wrote:
> 
> On 10/2/07, syg6 <[EMAIL PROTECTED]> wrote:
> 
>>
>> Thanks for your response Mike. I think you must have copy-pasted from
>> another
>> post or something, I am not working with a Country object. But I think
>> your
>> idea applies to both of my scenarios.
> 
> 
> Correct. It is a copy and paste from the relevant post on the thread.
> 
> 
> 
>> In scenario (1) I already have a PropertyEditor defined for
>> StreetSection.
>> It looks like this:
>>
>> public class StreetSectionPropertyEditor extends PropertyEditorSupport
>> {
>> public void setAsText(String id) {
>>      StreetSection streetSection = streetSectionManager.get(new
>> Long(id));
>>      setValue(streetSection);
>> }
> 
> 
> Please be careful about handling null values - you may/may not need this
> depending on the details of your implementation. You do need a getAsText
> method to ensure the field gets properly populated with the id for an
> existing establishment.
> 
> 
> 
>> And it seems to work fine. I don't have a getAsText() defined and it has
>> worked until now. But I am unsure of what I should use in the
>> establishmentform.jsp. Should I use:
>>
>> <form:hidden path="streetSection" id="streetSection" /> or
> 
> 
> This is the one you should use as it will use your property editor to
> correctly bind your object to the existing instance in your database.
> 
> 
> 
>> <form:hidden path="streetSection.id" id="streetSection.id" /> ?
> 
> 
> This will create a new StreetSection and attempt to save it. Presumably
> this
> is not what you want?
> 
> 
> 
>> It was working ok using 'streetSection' instead of 'streetSection.id' but
>> I
>> had problems when saving a NEW establishment (it worked fine when saving
>> an
>> existing Establishment curiously enough ...), 'can't save a transient
>> object' error. Could this be because I don't have getAsText() defined?
> 
> 
> Probably due to a cascade being set on the establishment object. Try
> without
> cascading save on the relationship. Judging by your jsp code this should
> always be null for a new establishment object?
> 
> Perhaps you could post the details of the error and we can try and help?
> 
> 
> 
>> In scenario (2), how would I go about creating an
>> EstablishmentContainerPropertyEditor? What I would need to do is tell
>> Spring, 'Hey! Create an EstablishmentContainer object with '1' for
>> idEstablishment, '2' for idContainer and '50' for quantity, and add it to
>> the list of EstablishmentContainers, using values from the .jsp, either a
>> multi-select or hiddens. But the setAsText() method takes only one
>> string,
>> usually an id. Do I need to override some other method in
>> PropertyEditorSupport?
> 
> 
> Property editors only do one thing: Text -> Object and Object -> Text. So
> they are useful if you want to build up one or more relationships between
> the object you are editing in the form and existing objects in the
> database.
> If what you are talking about is creating a new set of objects, then your
> form needs to address that -> your form would create new
> EstablishmentContainer objects and use property editors to build the
> relationship between EstablishmentContainer -> Establishment and
> EstablishmentContainer -> Container. Exactly how to go about this largely
> depends on how you want to manage the whole lot on the jsp page. If you
> have
> something that works, then that is the best way!
> 
> Spring does have the ability to bind to elements in an ordered list by
> using
> [index] type syntax, e.g. establishmentContainer[1]. Doing a Google search
> on 'Spring MVC bind list' will bring up a whole list of sites that discuss
> this in more detail.
> 
> Mike.
> 
> 
>> I think this is the way to go though, just not sure how to do it.
>>
>> Thanks!
>> Bob
>>
>>
>>
>>
>> Mike Horwitz wrote:
>> >
>> > I believe you could resolve both cases by registering custom editors in
>> > your
>> > controllers - this would allow Spring MVC to automatically convert
>> between
>> > the object and its string representation. See the thread on this
>> > discussion
>> > for more details http://tinyurl.com/3yghfd:
>> >
>> > You are going to need to provide *Spring* *MVC* with a way to get from
>> an
>> > id
>> > to a country and vice-versa.  As you correctly point out this is done
>> by
>> > registering a custom property editor in your controller. To do this you
>> > need
>> > to:
>> >
>> > 1) Extend the class *PropertyEditorSupport* to create the property
>> editor:
>> >
>> http://java.sun.com/j2se/1.5.0/docs/api/java/beans/*PropertyEditorSupport*.html
>> > <
>> http://java.sun.com/j2se/1.5.0/docs/api/java/beans/PropertyEditorSupport.html
>> >
>> >
>> > You need to override the getAsText() and setAsText() methods. The first
>> > should call getValue() and return the id as text, and the second should
>> > accept a text id and call setValue() on the editor with the
>> corresponding
>> > country object.
>> >
>> > 2) You then register this custom editor using one of the appropriate
>> > methods
>> > on your controller: initBinder() see api on http://tinyurl.com/2sutrm
>> >
>> > And it should all work like magic....
>> >
>> > Mike.
>> >
>> >
>> > On 10/2/07, syg6 <[EMAIL PROTECTED]> wrote:
>> >>
>> >>
>> >> I have a couple scenarios, one typical the other not so much, that I
>> am
>> >> trying to implement as quickly and easily as possible.
>> >>
>> >> The first is pretty straight-forward:
>> >>
>> >> @Entity
>> >> public class Application
>> >> ...
>> >> private StreetSection streetSecion;
>> >> ...
>> >> @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
>> >> @JoinColumn(name="streetSection", nullable=false)
>> >> public StreetSection getStreetSection()
>> >> {
>> >> return streetSection;
>> >> }
>> >>
>> >> In my form, which is the correct way to do the input?
>> >>
>> >> <form:hidden path="streetSection" id="streetSection" />
>> >>
>> >> or
>> >>
>> >> <form:hidden path="streetSection.id" id="streetSection.id" />
>> >>
>> >> In my testing I have found that they both work but each one has its
>> own
>> >> little quirks. For example, if I use 'streetSection.id', when it's a
>> new
>> >> Application the page crashes because streetSection.id is null. So I
>> have
>> >> to
>> >> put a <c:if> in there and if it's null just use a normal <input
>> >> type='hidden'> tag.
>> >>
>> >> If I use 'streetSection' I believe (I've done so many tests I forget
>> ...)
>> >> that Hibernate is giving me 'can't save transient object' errors.
>> Anyway,
>> >> just curious what the best practice is.
>> >>
>> >> The other scenario is more complicated. I have an object,
>> Establishment,
>> >> and
>> >> another, Container, and they both have a list of
>> EstablishmentContainer
>> >> objects, which saved in a join table that has an attribute, quantity.
>> So
>> >> each POJO, Establishment and Container, have a OneToMany relationship
>> >> with
>> >> EstablishmentContainer, and EstablishmentContainer has a ManyToOne
>> >> relationship with both Establishment and Container. This is apparently
>> >> the
>> >> best way to map join tables with attributes.
>> >>
>> >> @Entity
>> >> public class Establishment
>> >> ...
>> >> private List<EstablishmentContainers> establishmentContainers;
>> >> ...
>> >> @OneToMany(mappedBy="establishment", fetch = FetchType.EAGER, cascade
>> =
>> {
>> >> CascadeType.PERSIST, CascadeType.MERGE })
>> >> public List<EstablishmentContainer> getEstablishmentContainers()
>> >> {
>> >> return establishmentContainer;
>> >> }
>> >>
>> >> @Entity
>> >> public class Container
>> >> ...
>> >> @OneToMany(mappedBy="container")
>> >> public List<EstablishmentContainer> getEstablishmentContainers ()
>> >> {
>> >> return establishmentContainers;
>> >> }
>> >>
>> >> @Entity
>> >> public class EstablishmentContainer extends
>> >> {
>> >>        private Long id;
>> >>        private Establishment establishment;
>> >>        private Container container;
>> >>
>> >>        private int quantity;
>> >> ...
>> >> @ManyToOne
>> >> @JoinColumn(name="idEstablishment")
>> >> public Establishment getEstablishment()
>> >> {
>> >> return establishment;
>> >> }
>> >>
>> >> @ManyToOne
>> >> @JoinColumn(name="idContainer")
>> >> public Cubo getContainer()
>> >> {
>> >> return container;
>> >> }
>> >>
>> >> @Column(name="quantity")
>> >> public int getQuantity()
>> >> {
>> >> return quantity;
>> >> }
>> >>
>> >> In my EstablishmentFormController do I have to do the following for
>> each
>> >> EstablishmentContainer created in the page:
>> >>
>> >> 1. instantiate an EstablishmentContainer object
>> >> 2. fill it it request parameters by hand
>> >> 3. add it to a List
>> >> 4. assign that list to my Establishment object
>> >>
>> >> ... for the EstablishmentContainers list to be properly saved when I
>> do
>> >> an
>> >> establishmentManager.save()?
>> >> This is what I am doing currently and it works but it seems to me that
>> if
>> >> I
>> >> put the following in my jsp:
>> >>
>> >> input type="text" id="establishmentContainers.container.id"
>> >> input type="text" id="establishmentContainers.establihsment.id"
>> >> input type="text" id="establishmentContainers.quantity"
>> >>
>> >> Spring should be able to populate the List of EstablishmentObjects
>> >> automatically, just as in the first example it populates my
>> >> Application.StreetSection object when I put a
>> >>
>> >> input type="text" id="application.streetSection"
>> >>
>> >> element in the page. If it's not possible I can keep doing it the way
>> I
>> >> currently do, I just don't want to reinvent the wheel.
>> >>
>> >> Sorry for the long post. I look forward to any and all responses.
>> >> Bob
>> >>
>> >> --
>> >> View this message in context:
>> >>
>> http://www.nabble.com/Best-way-to-save-ManyToOne-relationships-with-Hibernate-and-Spring-MVC-tf4553758s2369.html#a12995187
>> >> Sent from the AppFuse - User mailing list archive at Nabble.com.
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: [EMAIL PROTECTED]
>> >> For additional commands, e-mail: [EMAIL PROTECTED]
>> >>
>> >>
>> >
>> >
>>
>> --
>> View this message in context:
>> http://www.nabble.com/Best-way-to-save-ManyToOne-relationships-with-Hibernate-and-Spring-MVC-tf4553758s2369.html#a12996194
>> Sent from the AppFuse - User mailing list archive at Nabble.com.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>> For additional commands, e-mail: [EMAIL PROTECTED]
>>
>>
> 
> 

-- 
View this message in context: 
http://www.nabble.com/Best-way-to-save-ManyToOne-relationships-with-Hibernate-and-Spring-MVC-tf4553758s2369.html#a12999381
Sent from the AppFuse - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to