The OData standard is pretty straight forward when it comes to doing queries and aggregations on fields, but I am having trouble wrapping my head around querying/aggregating against a field that is a collection or map.
For instance, lets say I have the following random class:
public class Teacher{
public String name;
public String city;
public List<Class> classes;
public Set<TeachingAssistant> TAs;
public Map<Class,List<Student>> studentsPerClass;
public Teacher(...){
//init all variables
}
}
Now, this is just an example. For the purpose of this example, the teacher class is the only way to get at students, Tas, and Classes. So, all of my queries and aggregations will need to be run off a collection of teachers. With that in mind, I have some questions:
How do I do aggregations on the list of classes? Like if I wanted to know the number of classes offered by a teacher, how would I do that in an OData query?
For instance, I would like to do something like:
.../Teachers?$apply=aggregate(classes with CountDistinct as totalClasses)
or maybe:
.../Teachers?$apply=aggregate(classes(*) with CountDistinct as totalClasses)
Would either of these be the correct way?
If I want to query a specific item in a list or set, how do I access it? A Set in java is not ordered and does not have anything for me to access it like setName('<value>'). For lists, would I just have to say listName('<num_index>')?
Related
I am trying to make this example as natural as possible to make it simple.
Lets say I have groups of items. eg item1, item2, item3, item4 etc.
Currently item is represented by struct:
// only contains data
struct item{
string name;
std::vector<string> parts_name;
std::vector<double> parts_price;
std::vector<string> item_color;
...
};
itemx item1, item2...
Then I have class called items
class items{
public:
// return name of all items
vector<string> get_all_item();
// return price of all parts
vector<double> get_all_parts_price();
private:
// hold vector of item
vector<shared_ptr<item>> list_of_items;
// name of item and its parts price
// eg: <item_1_part_1, $1.3>
// eg: <item_1_part_2, $2.3>
// eg: <item_2_part_1, $4.3>
map<string, double> parts_prices;
};
The problem with my current items class is that it is growing really huge,
as feature of item increases.
My solution: make struct item contain function which distributes load
to struct item from class items.
Is there any other better way or any design pattern that is meant for this kind of problem?
It is hard to tell you how to "design" your application based on your input - and I think you are focusing on the wrong aspect here. Your item struct contains vectors. That implies plural. But still, the class is called item.
In that sense: don't think about patterns here. Instead, step back and have a much closer look at the "real world things" you intend to model. You see, the core point of objects and classes is to built a model of the domain you are dealing with.
So a non-answer here: carefully look into the "real-world" relation that your objects have, and then focus on creating a OO model that is helpful to do work flows you intend to implement.
Let's say I have a list of Person with some attributes. For each object in this list I want to create a new Person object but only based on some of its attributes.
The Person object has the following attributes : age, name, disease.
I want to create a new Person only on its age and name. The disease attribute must be confidential.
How could I do that ?
Thanks in advance !
You very easily could do this by creating a new object entirely which does not hold that information. For example, you could make a class such as this
public class PersonNoDisease {
private int age;
private String name;
...
}
If you want to make sure that PersonNoDisease still has many of the same methods that the original person class did, you should create an interface that they both implement to ensure that they both have the methods which you think they should both have. If you don't have getters in the Person class, you should make those so that it will be easier to initialize this new class.
I have a class which is used to create connection with database:
class DBHandler
{
public:
DBHandler();
~DBHandler();
int connect();
int execQuery( string query);
string getField( int row, int col);
};
Now there is another class which is used to fetch some info from database,
class DBManager
{
public:
DBManager();
~DBManager();
//Approach 1
string getUsername()
{
//create a query here and use object of DBHandler class to execute it.
}
//Approach 2
string getUsername (struct QueryDetails& qDetails)
{
//create query using fields of structure and execute the query using DBHandler class.
}
};
Now here is the problem:
1 ) which approach should I follow:
A) If I use approach 1, then I need to hard code query.
B) If I use approach 2, then I need to fill structure each time before calling to function getUsername.
2 ) Is there any better solution except these two which would be generic ?
PS : Definition of structure
struct QueryDetails
{
string tableName;
vector<string> colList;
...
};
Your question is very broad, and the elements you give do not permit to propose you an objective best answer.
Your approach 1 has the following advantages:
it is a robust and secure approach : The queries are written with knowledge of the relevant object
if the database evolve it's easy to find out (text search) where specific queries are made for the tables, and updated the querying code for your object
if your object evolves, needless to say, that you'll immediately realise what you have to change on the database side
The main inconvenience, is that you're tightly linked to the database. If tomorrow you change from PostGres to something else, you have to rewrite every query.
Your approach 2 has the following advantages:
It is very flexible
If your database change, you have to change only the generic functions.
The inconvenience is that this flexibility bears a lot of risks for the maintenance: you can't be sure that the correct query is send by the client, and impact assessment of database layout changes are very difficult to assess.
So finally, it's up to you to decide which one would more fit your needs.
I'd personally tend to favour 1. But this is subjective, and I'd anyway introduce an additional layer to make the application code more independent of the database system that implements access to database.
However, depending on your need, a greater flexibility could be of advantage. For instance, if your class is in fact meant to be a middle layer for other calsses to fetch their own data, then approach 2 could be the best option.
Edit: I called it association because in my head it should be this, but it seems that I implement it as an aggregation... This can be also discussed...
Context
What you learn in IT is that when you do associations, you should use pointers.
For example: You have 2 objects: Person and Movie. One Person can do several Movie and one Movie can be done by/with several Person. You would then have:
class Person
{
public:
Person::Person();
int id;
vector<Movie*> movies;
};
class Movie
{
public:
Movie::Movie();
int id;
};
main()
{
Person person;
Movie *movie = new Movie;
person.movies.push_back(movie); // With a setter it would be better but...
}
or something like this (please correct me if I do something wrong =D)
Where the troubles appear
Now you have many persons and movies and you want to save it somewhere: in a database.
You get your person
You get all the movies it is associated with in order to construct the whole object.
But how do you get them?
Do you reconstruct a new pointer of Movie for each Person concerned that you associate ?
You lose then the association property that allow the objects to be linked but live their own life.
Do you load all the database in RAM and... ok forget this
What is the way to do it cleverly? What is the proper way given by documentations?
I'm interested in simplified/pseudo code as examples, dissertation... Thx a lot !
Your question is very broad, and there's a number of approaches, how to bind database tables (and represent their foreign key connections).
It's not really only how to represent/handle that kind of Domain Model snippet, you're presenting in your code sample here.
#Martin Fowler provided the EAA pattern catalogue you could reasonably research, and apply appropriate patterns for these kind of object <-> relational mapping problems you address.
I am trying to write a REST service with Jersey where the GET method should write me a list of objects. The input to the GET method should take the ids of the list.
Say I will pass n numbers of EmployeeId and the service should return me a list of employees.
If it is not possible to have #Consumes in the GET method, will there be any problem in using other methods of http like PUT or POST to retrieve the list of objects?
Using POST and PUT for resource retrieval contradicts the conventions established for the usage of REST over HTTP. Switching to either of them just for the sake of using a #Consumes annotation is simply wrong.
If you need to provide additional scoping information for a collection of resources, place it in the URL. Specifically, you can use query parameters. It's a common pattern to implement pagination this way (by providing some limit and offset parameters). Your use case is very similar.
Let's assume this is the URL of a collection of employee resources
GET http://www.example.com/employees
A single employee could be fetched like this:
GET http://www.example.com/employees/id1
If you want to retrieve several employees, you could use a query string like this:
GET http://www.example.com/employees?ids=id1;id3;id8
The identifiers do not need to be delimited by semicolons, this is just an example of a way you could fetch them. Remember that it's treated as a single parameter! You'll have to split the values.
Here's how you could read such a list from the URL above
#Path("employees")
#GET
public Response getEmployees(#QueryParam("ids") String employees){
List<String> ids = Arrays.asList(employes.split(";"));
// Validate the ids, get data from a database,
// prepare a response and return it
}
Parsing the list can be cumbersome, especially if you want to validate the ids somehow. Jersey has a neat feature you can use here. If a class has a single-string-parameter constructor or a SomeType parse(String) method, it can be injected by the framework by parsing the string passed as a parameter (QueryParam, PathParam, FormParam, etc.)
You can take advantage of it to make your resource class cleaner.
#Path("employees")
#GET
public Response getEmployees(#QueryParam("ids") Employees e){
doFancyStaffWithAValidListOfEmployees(e.asList());
//prepare a response
}
Where Employees is a class with a String constructor or a parse method, containing all the splitting and validation logic, possibly even some database queries.
Here's a nice article on writing such parameter classes