I use request vars to pass these things around in my own code, so merging is
pretty trivial. For example:
object employee extends RequestVar[Can[Employee]](Empty)
def viewEmployee (xhtml : NodeSeq) : NodeSeq =
employee.map(Model.merge(_)).map({ empl =>
...
bind(...)
}) openOr Text("Invalid Employee for View")
Note the double map call. The first merges, the second actually does the
binding. If you preferred to load from the DB each time you could do
def viewEmployee (xhtml : NodeSeq) : NodeSeq =
employee.map(Model.getReference(classOf[Employee], _.id)).map({ empl =>
instead. In either case this is simple enough that I haven't really bothered
looking for any cleaner solution. One thing I'd note is that generally in
Hibernate and JPA, keeping a session open across multiple web requests is
frowned upon. I don't know enough about the guts of SEAM to know if they're
really doing that, or using some magic to make it appear that they are. If I
remember correctly, in SEAM your objects are injected and outjected by SEAM
itself, so they could easily be intercepting things to make it kosher. In
any case, using the EM this way is outside my experience so if things start
going screwy I don't know how much I can help.
Derek
On Sun, Dec 7, 2008 at 8:44 AM, philip <[EMAIL PROTECTED]> wrote:
>
> Hi Derek,
>
> The problem I am thinking about is if you loaded for example, a list
> of "Employees" your going to show in a table.
> In your table you have a view button to view the employee, since you
> used JPA to load the list in the first place but now since the EM is
> finished from the first request and now we are on a second request
> with a new EM instance. If we try to navigate the lazy loading
> relationships, it won't work, it will throw a LazyLoadingException.
>
> So what you do - is your merge the entity back and the load it back
> from the database and then navigate the relationship.
> But if the EM was around all the time, cross requests, over the
> session then you could navigate the relationships without merge. I
> was suggesting the stateful snippit which is holding these lazy
> loading relationships should hold the EM since the entitys are
> normally on the stateful snippet.
>
> Thanks, Philip
>
>
> On Dec 7, 10:47 pm, "Derek Chen-Becker" <[EMAIL PROTECTED]> wrote:
> > I've been doing Hibernate and JPA long enough that reattaching instances
> at
> > method entry is somewhat habitual for me. Josh makes a good point about
> > being aware of the transaction, but in my experience the request method
> is
> > short-lived and it's usually not a problem. As for using a Stateful
> session
> > snippet to hold the EM, I think you want to look at the Model class; we
> use
> > a request var that essentially exists for the lifetime of the request to
> > hold the EM. That avoids tying the EM to a single snippet class (which
> may
> > or may not exist for every request) and makes it globally available to
> all
> > of your code if you want to use separate logic handling classes.
> >
> > Derek
> >
> > On Sun, Dec 7, 2008 at 6:18 AM, Josh Suereth <[EMAIL PROTECTED]
> >wrote:
> >
> >
> >
> > > As a side note...
> >
> > > The LazyInitialization exception wasn't an issue for me when using the
> > > "OpenSessionInView" pattern. However it became a large issue when
> trying
> > > to use hibernate to back a thick-client GUI. With what I've used of
> lift,
> > > I can't see JPA being any more difficult to manage then using another
> > > web-framework (perhaps even simpler in some regard). The key is just
> to
> > > understand what leaving the hibernate session open does to your
> transaction
> > > length and how you cna remedy troubles as you see them.
> >
> > > -Josh
> >
> > > On Sat, Dec 6, 2008 at 9:59 PM, philip <[EMAIL PROTECTED]> wrote:
> >
> > >> Hi Derek,
> >
> > >> Thanks, these are good reasons to use the JPA.
> >
> > >> About the use of the JPA in SEAM - the SEAM in Action (http://
> > >> manning.com/dallen/) book says
> > >> "Lazy loading of entity associations has unfortunately established a
> > >> bad reputation. The first thing that comes to mind in most developers'
> > >> minds when you talk about lazy loading is Hibernate's
> > >> LazyInitializationException. The culprit is the detached entity
> > >> instance.
> > >> ...
> > >> If the persistence manager is closed after the action method is
> > >> invoked, the Course instance is detached when the view is rendered.
> > >> ...
> > >> A call to the method getHoles() triggers an exception because the
> > >> EntityManager that loaded the Course instance is no longer available
> > >> to further communicate with the database. The same problem arises on
> > >> postback, even if a lazy association wasn't hit in the view."
> >
> > >> So within Liftweb it would then make sense to place the JPA
> > >> persistence manager within a stateful snippet. Since the snippet is
> > >> bound to the session, then navigation of the lazy loading entitys
> > >> wouldn't cause a LazyInitializationException?
> > >> Is this what is happening on the JPA example within Liftweb? it
> > >> doesn't look like it - in file Books.scala
> > >> def add (xhtml : NodeSeq) : NodeSeq = {
> > >> def doAdd () = {
> > >> Model.merge(book)
> > >> redirectTo("list.html")
> > >> }
> >
> > >> The SEAM book says
> > >> "Merging is a crude operation and should be avoided if possible. It
> > >> first loads an entity
> > >> instance with the same identifier as the detached instance into the
> > >> current persistence
> > >> context, resulting in a database read. Then, the property values from
> > >> the detached
> > >> instance are copied onto the properties of the managed instance. The
> > >> main problem
> > >> with this operation is that merging clobbers any changes that may have
> > >> been made to
> > >> the database record since the detached instance was retrieved (unless
> > >> object version-
> > >> ing is used). There are other problems as well. If an entity instance
> > >> with the same
> > >> identifier as the detached instance has already been loaded into the
> > >> current persis-
> > >> tence context, a non-unique object exception is thrown because the
> > >> uniqueness con-
> > >> tract of entities in a persistence context is violated. You may also
> > >> run into a lazy
> > >> loading exception if you hit an uninitialized association on the
> > >> detached instance dur-
> > >> ing the merge. Avoid merging if at all possible. "
> >
> > >> Thanks, Philip
> >
> > >> On Dec 6, 10:47 pm, "Derek Chen-Becker" <[EMAIL PROTECTED]>
> wrote:
> > >> > Here are a couple of features that JPA has that can be very useful:
> >
> > >> > 1. More powerful query language. The tradeoff is that HQL is not
> > >> > type-safe like Mapper's findXXX methods, so you need to test your
> > >> query
> > >> > syntax to make sure it returns what you want. Granted, you can
> use
> > >> SQL
> > >> > directly in Mapper, but it's tied directly to the DB while HQL
> allows
> > >> you to
> > >> > abstract away some of the smaller details, particularly with join
> > >> > associations. However, HQL does allow you to easily
> > >> > 1. Do flexible joins between large graphs of objects
> > >> > 2. Select scalar values (i.e. "select distinct player.age from
> > >> > TeamMember player where ...")
> > >> > 3. Prefetch otherwise lazily loaded properties ("select player
> > >> from
> > >> > TeamMember left join fetch player.coach")
> > >> > 2. IMHO, better definition of associations between classes.
> > >> > HasManyThrough works well for a subset of usages, but it:
> > >> > 1. Can't be treated as a real, live collection (no updates, no
> > >> > cascades)
> > >> > 2. Only runs once (it's lazy). Given the duration of a web
> request
> > >> > cycle this would usually not be a big deal unless you have a
> > >> > high number of
> > >> > concurrent users operating on the same data
> > >> > 3. Doesn't map well to many-to-many relationships; you have to
> > >> build
> > >> > your own binding entity to represent the join table
> > >> > 3. JPA has a number of implementations available for an
> intermediate
> > >> > cache to improve performance
> > >> > 4. JPA supports locking of objects for read and write
> >
> > >> > That's what I can come up with off the top of my head. Having SEAM
> > >> generate
> > >> > the classes for you is also nice, although I'm sure a similar tool
> could
> > >> be
> > >> > written for Mapper. Now, as for SEAM's (ab)use of the entity manager
> > >> (I'm
> > >> > assuming that's what you mean by transaction manager), I'm not so
> sure
> > >> that
> > >> > it's actually keeping the EM open across the entire "conversation",
> but
> > >> > rather providing an interface that makes it appear that it is. I saw
> > >> Gavin
> > >> > King here give a presentation on SEAM a few years ago and it sounded
> > >> like
> > >> > they were doing some magic behind the scenes to keep everything
> > >> coherent. I
> > >> > don't really know enough about it to argue for or against it, but
> > >> generally
> > >> > the idea is that by holding a transaction across the scope of an
> entire
> > >> > conversation you can treat a series of forms/pages as an atomic unit
> of
> > >> > work. I'm pretty sure Mapper doesn't have anything comparable, and
> > >> Mapper's
> > >> > concept of lazy loading isn't tied to having an open EM like it is
> in
> > >> JPA.
> > >> > That means that if something in Mapper is going to be lazily loaded,
> > >> it'll
> > >> > work no matter what.
> >
> > >> > Derek
> >
> > >> > On Fri, Dec 5, 2008 at 6:24 PM, philip <[EMAIL PROTECTED]>
> wrote:
> >
> > >> > > Hi,
> >
> > >> > > Why should I use JPA as vs using Liftwebs built in database
> mappers.
> > >> > > Lets say I build a 100 table mysql database, I'm mostly doing
> forms,
> > >> > > user input, tables out.
> > >> > > Is there something unattractive about using Liftwebs built in
> mapper?
> > >> > > I don't like the name MetaMegaProtoUser, but thats just
> aesthetics.
> >
> > >> > > Currently I can generate lots of Java JPA classes from database
> using
> > >> > > SEAMs generation ant script, my thought was then to use those Java
> > >> > > classes and convert them over to Scala JPA as in the example
> project.
> > >> > > However I don't know why to do this as opposed to using Liftweb's
> > >> > > mapper.
> >
> > >> > > I'm also worried about something and not sure if I should be
> worried
> > >> > > about it. JBoss SEAM has this concept of conversational state and
> it
> > >> > > can keep the JPA transaction manager open from one page to another
> > >> > > page, through use of the session. SEAM claims this is a good idea
> and
> > >> > > we shouldn't be closing the transaction manager on each call. Also
> it
> > >> > > can keep a transaction open for a long time through page views.
> > >> > > However, I don't see why or when I would need to do a transaction
> with
> > >> > > multiple page views involved in it. I mean, even large websites
> like
> > >> > > facebook, I doubt they do this - they use PHP. Why not just do the
> > >> > > transaction in one call?
> >
> > >> > > SEAM also has this concept of avoiding the Hibernate
> > >> > > LazyInitializationException, so if your navigating down some
> objects
> > >> > > relations, it will load the lazy relations as you navigate down.
> So
> > >> > > you don't need to re-query the database, because of the
> transaction
> > >> > > manager being open between pages, it will load the Hibernate
> objects
> > >> > > that are lazy loaded as you navigate a O-R structure.
> > >> > > Of course this sounds attractive in regards to SEAM.
> > >> > > What if I navigated structures in Liftweb using the built in
> mapper -
> > >> > > is there any concern I should have?
> >
> > >> > > Thanks, Philip
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---