Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Query based on values in a related collection?

    I can't find an example of querying a datasource based on property values in a related collection. For example, I would like to show all of the orders that have a certain product number. Another example would be to find orders whose line item quantity were greater than a certain value.

    Maybe I just can't find the right search terms (apropos) in the forum, javadoc or Quick Start. In my different attempts I either get no results ("WHERE 1=2" is appended to the query), all of the records (no where clause at all is appended), or a javascript error (below).

    Thanks for any hints!

    Info:

    1. SmartClient Version: v8.2p_2012-04-30/Enterprise Deployment (built 2012-04-30)

    2. firefox 10.0.2

    3. The issue is client-side, I believe.

    4. N/A

    5. Stacktrace:
    Code:
    com.google.gwt.core.client.JavaScriptException: (null): null
        at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:248)
        at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:289)
        at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(JavaScriptHost.java:107)
        at com.smartgwt.client.widgets.grid.ListGrid.fetchData(ListGrid.java)
        at com.joe.client.presenter.SandboxPresenter.prepareFromRequest(SandboxPresenter.java:86)
        at com.gwtplatform.mvp.client.proxy.ProxyPlaceAbstract$3$1.execute(ProxyPlaceAbstract.java:205)
        at com.google.gwt.core.client.impl.SchedulerImpl$Task$.executeScheduled$(SchedulerImpl.java:50)
        at com.google.gwt.core.client.impl.SchedulerImpl.runScheduledTasks(SchedulerImpl.java:228)
        at com.google.gwt.core.client.impl.SchedulerImpl.flushPostEventPumpCommands(SchedulerImpl.java:388)
        at com.google.gwt.core.client.impl.SchedulerImpl$Flusher.execute(SchedulerImpl.java:78)
        at com.google.gwt.core.client.impl.SchedulerImpl.execute(SchedulerImpl.java:138)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
        at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
        at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
        at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
        at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
        at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
        at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
        at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
        at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:216)
        at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
        at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
        at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
        at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
        at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
        at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
        at java.lang.Thread.run(Thread.java:736)
    6. sample code if applicable
    Code:
    		final DataSource orderDataSource = DataSource.get("order");
    		final ListGrid orderGrid = new ListGrid();
    		orderGrid.setDataSource(orderDataSource);
    		final Criterion searchCriterion = new Criterion("lineItems.productNumber", OperatorId.CONTAINS);
    		searchCriterion.setAttribute("value", new HashSet(Arrays.asList(new String [] {"1"})));
    		orderGrid.fetchData(searchCriterion);

    #2
    Code:
    searchCriterion.setAttribute("value", new HashSet(Arrays.asList(new String [] {"1"})));
    How did you get the idea for this line of code?? Seriously if there's some doc that you read that suggested this to you, we'd like to take a look and consider revising it.

    You just need "new AdvancedCriteria(fieldName, operator, value)" and that's it.

    The fieldName should be an actual fieldName, not a path to a field. If you are trying to do something like find all items within an order, then add another criteria that says the item's orderId must be equal to the ID of the order you are searching within.

    Comment


      #3
      I was experimenting, based on the idea from this post:
      http://forums.smartclient.com/showthread.php?t=10573

      In this example I'm not trying to find the items for an order. I'm trying to find orders which contain line items that have a given attribute value.

      Pseudo-code:
      Code:
      Select Order o
      Join o.lineItems AS lineItem
      Where lineItem.productNumber = "655321"

      Comment


        #4
        You should pass the productNumber as part of the criteria for a request against the "Order" DataSource, then server-side, do something similar to your pseudocode below to retrieve the correct Orders.

        If you're using SQLDataSource (the top recommendation) then that pseudocode is very nearly something you can plunk into a customized <whereClause>.

        Comment


          #5
          Thanks for the quick reply. I'll review both options.
          I had been hoping that there was something in the criteria api to abstract the joining across datasources.

          Comment


            #6
            We abstract the joining across DataSources via dataSourceField.includeFrom and similar mechanisms (SQL templating) that allow you to have a field that really comes form another entity/table yet can be queried, sorted, etc as though it were a normal field of the main DataSource.

            This case is a bit unusual because it's not quite a join or at any rate requires more than a straight join - your pseudocode is actually wrong as it would produce multiple copies of each order. You would need select distinct, grouping, or a sub-select to get the right result.

            Comment


              #7
              Originally posted by Isomorphic View Post
              You should pass the productNumber as part of the criteria for a request against the "Order" DataSource, then server-side, do something similar to your pseudocode below to retrieve the correct Orders.
              I'm trying to accomplish this by calling getCriteria() on the HibernateDataSource and then modifying the Hibernate Criteria object to get the results I'm looking for. Unfortunately, "getCriteria()" causes the datasource to attempt a query to retrieve the rowCount. This query throws an Exception because the underlying AdvancedCriteria/Hibernate-Criteria is not yet prepared to access the related properties.
              I'll try to put together a quick testcase this evening, but is it possible to either:
              1. make HibernateDataSource::buildCriteria public? and/or
              2. don't make a rowCount() projection query as part of HibernateDataSource::getCriteria()?
              Thanks.

              Comment


                #8
                Don't call undocumented methods, they aren't supported and may be moved or renamed at any time.

                There doesn't seem to be a reason to access the Hibernate Criteria for this use case as far as we can tell. You can modify the default DSRequest that is passed to you before execute()ing it, or you can do additional requests via just creating a new DSRequest and setting criteria on it - the QuickStart section on using DMI for business logic has a few examples.

                Comment

                Working...
                X