Completely new to Axon here.
I have a class defined in Kotlin:
data class ProjectedQuote(
#Id var submissionId: String,
var periodId: String,
var accountNumber: String
)
It gets instantiated and updated by event handlers, then it is returned in response to queries.
I'm needing to create a query that finds a ProjectedQuote instance by accountNumber, not id. I'm not sure how to do that.
To date, I've only done queries like:
SELECT q FROM ProjectedQuote q WHERE q.id LIKE CONCAT(:idStartsWith, '%') ORDER BY q.id
My narrowly-focused question is:
How do I write a query that finds ProjectedQuote using accountNumber instead of id?
My broader question is:
How can I see what fields are available to query by in the Axon databases?
Query messages typically read data from the view models created by the event listeners. Event listeners typically execute logic based on decisions that have been made by the command model. Usually, this involves updating view models or forwarding updates to other components.
So the mechanism for creating and receiving views is entirely up to you. (jpa, spring data, mybatis, jdbc etc.) A good example the axon project is https://github.com/idugalic/digital-restaurant
What Sergey points out here too is very valid.
How you model your Query Model in such an application is entirely up to you. So pick JPA, JDBC, MongoDB, ElasticSearch, Neo4j..whichever format of containing the Query Model suites you best!
This freedom of storage mechanisms thus also points out that your Query Model isn't stored in an 'Axon Database'; it's stored in the database you have chosen.
In regards to how to model your queries, you could have a look at how QueryMessages and QueryHandlers can be used in Axon, over here. This is just another dedicated type of message from Axon's perspective, just like Command- and EventMessages.
Using Query Messages, you can specify the type of query you'd want to perform as a separate object, which is the query.
This query will in turn be handled by an #QueryHandler annotated function.
The #QueryHandler annotated function will in turn perform the actual operation to retrieving the model from the database you have chosen to use to store the model in.
Hope this gives you some insights!
Related
I'm developing a CorDapp but haven't implemented the schema as it is not a good practice.
But the code I have to get a particular record without using schema is first getting me all the states and then fetching a particular record, it is very time consuming as it is iterating through over each state object.
DataFeed, Vault.Update> dataFeed = proxy.vaultTrack(IOUState.class);
//this gives a snapshot of IOUState as of now. so if there are 11 IOUState as of now, this will return 11 IOUState objects
Vault.Page<IOUState> snapshot = dataFeed.getSnapshot();
for (StateAndRef<IOUState> state : snapshot.getStates()) {
if (state.getState().getData().getAssetId().equals(value)) {
cs = state.getState().getData();
}
}
Could you please suggest better approach to fetch a particular record from corda vault without using schema and iterating through over each state object.
Not sure how you come to the conclusion that using a schema is not a good practice. Do you have any data points to prove this? Or the source of this information would be helpful for us to understand the problem with implementing a schema.
Is's not possible to fetch a state based on one of its attributes without a schema. However, if you are specifically interested in fetching a state based on an ID (also considering your state is Linear/ Non-Fungible in nature), you could use a linear state. A linear state can be directly fetched from the vault using a LinearStateQueryCriteria.
val criteria = LinearStateQueryCriteria(linearId = listOf(linearId));
val results = vaultService.queryBy<LinearState>(criteria);
Who said implementing a schema is not a good practice?! Please post a link to where you read that.
You can't get a particular record from the vault (i.e. using a query on a certain attribute) without a custom schema.
I created custom table in corda using QueryableState. e.g. IOUStates table.
I can able to see the custom information getting stored in this kind of table.
but i observed that if party A and Party B is doing the transaction then this
custom information gets stored at both the places , e.g. IOUStates
table getting created at nodeA ledger as well as nodeB's ledger.
and custom information is stored in partyA's and PartyB's ledger.
My Question is :-
If some Transaction is getting processed from PartyA's node , then
I want to store part of the transaction's data i.e. custom data ONLY at partyA's Ledger.* level . i.e. off-Ledger of partA only.
It should not be shared with partyB.
In simple case , how to store Only node specific off ledger custom data ?
Awaiting for some reply...
Thanks.
There's a number of ways to achieve this:
Don't use Corda at all! If the data is truly off-ledger then why are you using Corda? Instead, store it in a separate database. Of course you can "JOIN" it with on-ledger data if required, as the on-ledger data is stored in a SQL database.
Similar to point one except you can use the jdbcSession() functionality of the ServiceHub to create a custom table in the node's database. This table can easily be accessed from within your flows.
Create a ContractState object that only has one participant: the node that wants to store the data. I call this a "unilateral" state, i.e. a state that only one party ever stores.
Most importantly, if you don't want to share some data with a counter-party then it should never be disclosed inside a corda state object or attachment that another party might see. Instead:
inside your flows, you can use the data encapsulated within the shared state object (e.g. the IOU) to derive the private data
alternatively if the data is supplied when the flow begins then store the private data locally using one of the methods above
In my application I'm pulling back a user's "feed". This contains all of that user's activities, events, friend requests from other users, etc. When I pull back the feed I'm calling various functions to filter the request along the way.
var userFeed = GetFeed(db); // Query to pull back all data
userFeed = FilterByUser(userFeed, user, db); // Filter for the user
userFeed = SortFeed(userFeed, page, sortBy, typeName); // Sort it
The data that is returned is exactly what I need, however when I look at a SQL Profile Trace I can see that the query that is getting this data does not filter it at the database level and instead is selecting ALL data in the table(s).
This query does not execute until I iterate through the results on my view. All of these functions return an IEnumerable object.
I was under the impression that LINQ would take all of my filters and form one query to pull back the data I want instead of pulling back all the data and then filtering it on the server.
What am I doing wrong or what don't I understand about the way LINQ evaluates queries?
If GetFeed returns an IEnumerable, FilterByUser will receive an IEnumerable. When it calls some LINQ operator, i.e. Where, it will use the IEnumerable Where, which will start to ask for information, which will eventually download the entire table. Change the type of GetFeed to IQueryable to make sure that IQueryable's LINQ operators are called instead, which will keep delaying the query.
I have an application with user and admin sections. If an admin updates data with the help of sql datasource then it's updated the database. However, when we retrieve data with linq query then it's showing its old value rather than the updated value.
After some time, the linq query automatically shows the correct value.
I think its caching the value, but I find myself helpless. Please help me with this.
When you say
when we retrieve data with linq query
Do you mean you call your select methods again or are you using the current in memory objects?
In either case, you can always refresh an entity with :
Context.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, entity)
Make sure that you're using your DataContext efficiently (ideally one per unit of work).
After each update, make sure you call DataContext.SubmitChanges(); to commit your changes back to the database.
Also be aware that any context you instanciate between your changes being added to another context and calling SubmitChanges() will not reflect those changes.
Just dipping my toes into Linq2sql project after years of rolling my own SQL Server DB access routines.
Before I spend too much time figuring out how to make linq2sql behave like my custom code used to, I want to check to make sure that it isn't already "built" in behavior that I can just use by setting up the relationships right in the designer...
Very simple example:
I have two tables: Person and Notes, with a 1 to many relationship (1 Person, many notes), linked by Person.ID->Note.PersonID.
I have a stored procedure (all data access is done via SP's and I plan on continuing that) which makes the Link2SQL a bit more work for me.
sp_PersonGet(#ID int) which returns the person record and sp_PersonNotesGet(#PersonID) which returns a set of related notes for this person.
So far so good, I have an object:
Dim myPerson As Person = db.PersonGet(pnID).Single
and I can access my fields: myPerson.Name, myPerson.Phone etc.
and I can also do a
Dim myNotes As Notes = db.PersonNotesGet(pnID)
to get a set of notes and I can iterate thru this list like:
For Each N As Note In myNotes
( do something)
Next
This all works fine...BUT....What I would prefer is that if I call:
myPerson = db.PersonGet(pnID)
that I also end up with a myPerson.Notes collection that I can iterate thru.
For Each N As Note In myPerson.Notes
( do something)
Next
Basically, Linq2SQl would need to call 2 stored procedures each time a Person record is created...
Is this doable "out of the box", or is this something I need to code around for myself?
This is normally what we would call child collections and they can be eager loaded or lazy loaded. Read these:
http://davidhayden.com/blog/dave/archive/2009/01/08/QuickExamplesLINQToSQLPerformanceTuningPerformanceProfilingORMapper.aspx
http://www.thinqlinq.com/default/Fetching-child-records-using-Stored-Procedures-with-LINQ-to-SQL.aspx
It uses partial classes. You can add your own "Notes" property to your Person class and initialize it in it's GETter function. This would be better than populating the notes every time you load a person record.
I believe that you can do this more or less out of the box, although I haven't tried it -- I don't use stored procedures with LINQ. What you would need to do is change the Insert/Delete/Update methods from using the runtime to use your stored procedures. Then you'd create an Association between your two entity tables which would create an EntitySet of Notes on the Person class and a EntityRef of Person on the Notes class. You can set this up to load automatically or using lazy loading.
The only tricky bit, as far as I can see, is the change from using the runtime generated methods to using your stored procedures. I believe that you have to add them into the data context as methods (by dropping it on your table from the server explorer in the designer) before it is available to use instead.