How to fetch a graph of persistent objects with one database call using JDO API? - jdo

I have various relations between my entities, and by default all relations use lazy loading. I don't want to use eager loading, but I want to be able to fetch some relation in certain query. (Like I can do using JPA's join fetch)
I tried to use named fetch group, but I'm not sure how to work with it. I want to tell JDO to create only one sql query with joins, and then build an entity graph for me.
<class name="Account" identity-type="application" table="account" detachable="false" >
<inheritance strategy="new-table" />
<field name="_accountId" value-strategy="sequence" sequence="ACCOUNT_ID_SEQUENCE"><column name="account_id" /></field>
<field name="_phone"><column name="phone" /></field>
<field name="_phoneCode"><column name="phone_code" /></field>
<field name="_phone2"><column name="phone2" /></field>
<field name="_phone2Code"><column name="phone2_code" /></field>
<field name="_state"><column name="state" /></field>
<fetch-group name="personInfo">
<field name="_personHistory" mapped-by="_account" delete-action="cascade">
<collection element-type="Person" />
<column name="account_id" />
</field>
</fetch-group>
</class>
And the code
PersistenceManager pm = getPersistenceManager();
Query query = pm.newQuery(Account.class);
FetchPlan fetchPlan = pm.getFetchPlan();
fetchPlan.addGroup("personInfo");
fetchPlan.setFetchSize(FetchPlan.FETCH_SIZE_GREEDY);
return (List<Account>) query.execute();

JDO FetchGroup/FetchPlan has more flexibility than anything JPA has to offer IMHO.
You define fetch groups for persistable classes following this link. So you can put particular fields in a FetchGroup. And then you add that fetch group to the FetchPlan. In the case of a query you set the FetchPlan of the query to include all fields of the candidate (and related objects) that you want to retrieve, as per http://www.datanucleus.org/products/accessplatform_5_0/jdo/query.html#FetchPlan

Related

Best pattern to manually parse arguments for query optimisation in GraphQL dotnet

We have a GraphQL dotnet implementation sitting on top of our existing app database.
<PackageReference Include="GraphQL" Version="3.3.2" />
<PackageReference Include="GraphQL.SystemTextJson" Version="3.3.2" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Transports.WebSockets" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore.SystemTextJson" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Ui.Playground" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Authorization.AspNetCore" Version="4.4.1" />
We have a fairly intertwined data structure, so when querying from some of our top level fields, and including some of their sub fields, we could be joining on a large number of tables. However, not every query would need all those joins.
I was hoping to be able to manually parse the context.Arguments in our Query ObjectGraphType when I am resolving it to eliminate the joins if a particular sub-field is not queried.
A very simple high level version of this would be as follows:
Field<ListGraphType<OrganisationType>>(
"organisations",
resolve: context =>
{
var retVal = database.Organisations();
//Are we joining on employers?
if(context.SubFields.ContainsKey("employers"))
{
retVal.Include(x => x.Employers.Where(x => x.Deleted != true))
.ThenInclude(x => x.Departments.Where(x => x.Deleted != true));
}
return retVal;
}
Where we only join on employers, if the user has queried that. However, the issue is that employers can have departments, employees, managers etc etc... and those themselves can have a large number of sub-properties.
Currently our query joins on pretty much every permutation of the query, producing a really hefty SQL query. Which is a lot of heavy lifting if the user only wants, the organisation name, and each employers name.
Filtering on the very top level is easy enough (as shown above) but I can't figure out how to query from that point onwards, I just seem to end up in an infinite loop of Children... for example:
var employerSubField = context.SubFields["employers"];
var otherJoins = employerSubField.SelectionSet.Children.Where(x => x.Children)
I can't seem to get a where name == "Employees" or anything like that. Do I need to cast the GraphQL.Language.AST.INode to something at some point? When I inspect the values at debug time it looks like I should be able to see the values I am after. But this won't compile.
var deptsField = employerSubField.SelectionSet.Selections.Where(x => x.Name == "departments");
I have found the following way to get the basic information out that I can then easily parse myself and add my own custom logic.
var query = context.Document.OriginalQuery.Substring(context.Document.OriginalQuery.IndexOf("{")).RemoveWhitespace();
returns:
{organisations{id,name,employers{id,name,clientNotes,departments{id,name}}}}

How to select all fields in a queryDef?

I want to select all fields in the recipients instead of selecting one by one
var query = xtk.queryDef.create(
<queryDef schema="nms:recipient" operation="getIfExists">
<select>
<node expr="[#firstName]"/>
<node expr="[#lastName]"/>
<node expr="[#middleName]"/>
<node expr="[#email]"/>
</select>
<where>
<condition expr={"#Id='93975738'"}/>
<condition expr={"#company='xxxx'"}/>
</where>
</queryDef>)
var result = query.ExecuteQuery();
logInfo(result.toXMLString());
After figuring it from Adobe Campaign Javascript API:
var query = xtk.queryDef.create(
<queryDef schema="nms:recipient" operation="select">
<where>
<condition expr={"#laId='93975738'"}/>
<condition expr={"#company='SERE'"}/>
</where>
</queryDef>)
query.SelectAll(false)
var result = query.ExecuteQuery();
logInfo(result.toXMLString());
Apparently queryDef.SelectAll(bolean duplicates) does it!

How to get query params when I use <form> with POST method to trigger Firebase http functions?

I am trying to pass some query params to my http function in Firebase in a secure way. My params are not really sensitive like passwords, etc, they are some booleans, etc that determines logic server side.
When I try a simple <form> with method GET or PUT the res.query shows the values not when I use POST.
<form id="form" action="https://us-central1-***.cloudfunctions.net/myfuncName"
method="post">
<input type="text" name="id" value="test">
</form>
I submit the form in Javascript by
this.getElementById("form").submit();
in my function I have :
function(req, res) {
const param = req.query;
console.log('query param is ' , param); //{} when form method is POST
}
I expect to be able to get id from res.query in my function but I get null {}. If I change method to GET or PUT then I see {id:test}.
Any suggestion on enhancing the security of this would be appreciate too. Thanks.
res.query allows you to get parameters coming from the query string of a request. A POST request doesn't use the query string, so you can't use res.query. POST sends parameters to the request body.
To access POST parameters in the request body that are coming form a form, you can use req.body as described in the Cloud Functions documentation.

make account.invoice form 'no editable' when invoice state is 'paid'

i try to make account.invoice form 'no editable' when invoice state is 'paid'.
This is my code in acount.invoice class:
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
result=super(account_invoice, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
if(view_type=='form'):
invoice=self.pool.get('account.invoice')
active_id=context.get('active_id',False)
current_state=invoice.browse(cr,uid,active_id).state
if current_state=="paid":
result['arch']='''<form string="Invoice" edit="false" ....................></form>'''
return result
but it looks like context.get('active_id',False) always return "false".
thanks in advance :)
You can edit the XML for the fields you don't want people to edit and give it an attribute like this:
<field name="your_field" attrs="{'readonly':[('state','in','paid')]}"/>
Or you can inherit the write method from the model and insert a check to see the current state and raise an exception.
EDIT:
You can hide/remove the buttons by editing the form
<form string="NAMEOFFORM" create="false" edit="false" version="7.0"></form>

Symfony One-To-One persists a new empty row in the database

I have two related entities, Variant and DimensionGroup.
A Variant can have a DimensionGroup, but is not required to.
Every time I create a new Variant, a new DimensionGroup row is created in the database, with every field set to null, except for its id, which is auto incremental.
I want not to have the DimensionGroup row in the database when I persist a Variant that does not have a DimensionGroup.
The mapping looks like this:
Variant.orm.xml
<one-to-one field="dimensionGroup" target-entity="Flexy\Ftwo\Store\Entity\DimensionGroup" mapped-by="variant">
<cascade>
<cascade-remove/>
</cascade>
</one-to-one>
DimensionGroup.orm.xml
<one-to-one field="variant" target-entity="Flexy\Ftwo\Store\Entity\Variant" inversed-by="dimensionGroup">
<join-column name="variant_id" referenced-column-name="id" nullable="true" />
</one-to-one>
What is wrong here?

Resources