spring data mongodb method query - java

Suppose my document contains two field - from and to. I want to fetch all the documents whose from is lessThanEqual the provided value and to is greaterthanEqual the provided value.
the way I can do that is
List<T> findAllByFromLessThanEqualAndToGreaterThanEqual(Integer from, Integer to)
I am using method query way to achieve it.
Now suppose I have a list of Integer, is there any efficient way to fetch the records in single query.
Something like instead of iterating over the list of Integer and firing the query again and again
List<T> list = someIntList
.stream()
.map(someInt -> someRepository.findAllByFromLessThanEqualAndToGreaterThanEqual(someInt, someInt))
.flatMap(Collection::stream).collect(Collectors.toList());
The above way will hit the database again and again, so is there any more efficient way to achieve it in a single query.

Related

Fetching a record from an arraylist that is made up of arrays of objects

I have a java arraylist that is made like this:
{[{},{}], [{},{}], [{},{}], [{},{}]} of around four thousand records.
I have a particular key through which I want to search in one of the objects in this list and fetch that particular array where that
record matches. The search key is a string.
Is there a solution to this without traversing through the entire list.
It is basically a list that is constructed like this:
List<Object[]> list = new ArrayList<>();
I am using this to fetch the the data from two tables using a join. Individual records of each tables map to these objects.
Say table1: {a:1,b:2,c:3} and table2: {x:1,y:2,z:3}
the data returned would be
{[{a:1,b:2,c:3}, {x:1,y:2,z:3}],[{a:2,b:3,c:4}, {x:2,y:3,z:4}]}
How will I search for say in which array in the list is a=2.
Thanks
If you do not want to be a victim of the linear search, you should consider using another type of data structure than List.
The use case you described seems like a good match for a Map in general. If you want constant time key lookup, consider using HashMap instead.

Non-serializing in-memory database

I have the following problem:
There is a Set<C> s of objects of class C. C is defined as follows:
class C {
A a;
B b;
...
}
Given A e, B f, ..., I want to find from s all objects o such that o.a = e, o.b = f, ....
Simplest solution: stream over s, filter, collect, return. But that takes a long time.
Half-assed solution: create a Map<A, Set<C>> indexA, which splits the set by a's value. Stream over indexA.get(e), filter for the other conditions, collect, return.
More-assed solution: create index maps for all fields, select for all criteria from the maps, stream over the shortest list, filter for other criteria, collect, return.
You see where this is going: we're accidentally building a database. The thing is that I don't want to serialize my objects. Sure I could grab H2 or HSQLDB and stick my objects in there, but I don't want to persist them. I basically just want indices on my regular old on-the-heap Java objects.
Surely there must be something out there that I can reuse.
Eventually, I found a couple of projects which tackle this problem including CQEngine, which seems like the most complete and mature library for this purpose.
HSQLDB provides the option of storing Java objects directly in an in-memory database without serializing them.
The property sql.live_object=true is used as a property on the connection URL to a mem: database, for example jdbc:hsqldb:mem:test;sql.live_object=true. A table is created with a column of type OTHER to store the object. Extra columns in this table duplicate any fields in the object that need indexing.
For example:
CREATE TABLE OBJECTLIST (ID INTEGER IDENTITY, OBJ OTHER, TS_FIELD TIMESTAMP, INT_FIELD INTEGER)
CREATE INDEX IDX1 ON OBJECTLIST(TS_FIELD)
CREATE INDEX IDX2 ON OBJECTLIST(INT_FIELD)
The object is stored in the OBJ column, and the timestamp and integer values for the fields that are indexed are stored the the extra columns. SQL queries such as SELECT * FROM OBJECTLIST WHERE INT_FILED = 1234 return the rows containing the relevant objects.
http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_sql_conformance

How can i reverse a read-only-list in java?

I'm having a problem reversing a list object that is fetched from a database using jpa.
I'm using Collections.reverse(myListObject).
What I intend to do is to retrieve the list from database, reverse it, then send it to my jsp page.
I get the below error:
"java.lang.UnsupportedOperationException: Result lists are read-only."
Any solution for this?
Since the list is coming from JPA, the first approach is to avoid reversing the list in memory, doing it on RDBMS side instead. Change the ORDER BY clause of your JPQL if this approach is viable in your situation.
If this cannot be done, for example, because you have no direct control over your JPQL, reverse a copy:
List<MyType> rev = new ArrayList<MyType>(myListObject);
Collections.reverse(rev);

Any way to make hibernate query return key-value map automatically (omit "as")?

Since data stored in Mysql always has a column name, I thought it will be great if there is a way to retrieve the records in a key-value map.
The Hibernate mechanism for join queries can't help too much, as we could only retrieve the Object[] result and deserialize the result ourself, or we could use this:
This is most useful when used together with select new map:
select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
from Cat cat
The query above gives a way of retrieving a map, but we have to define the key of the map(with as), I think it's just a case-by-case solution, it is not very elegant to hard-code the field name.
Isn't it better and generic that we find a way to automatically define the key of the retrieved map with just the column name? So can we send a map with all the fields and let the application choose which field to use?
Even if there was such a feature how could Hibernate decide which is the Map key and which columns from the Map value.
The most flexible solution is to define a DTO which will be used to hold the selected projection:
select new my.package.DTO(field1, field2, .., fieldn) from ...
And you simply pass the result to a custom result transformer, which contains the exact result set key mapping logic.

Flatten a collection as part of an HQL query?

I have a requirement to use a reporting-friendly query from HQL. That is, each column is represented by a standard Java type (Long, Integer, String, List) rather than a mapped class. The values will be used by a third party library, so I have very limited control over post-processing.
My example object tree looks like this:
a.x
a.y (a collection of z)
a.y.z[0].v
a.y.z[1].v
a.y.z[2].v
I would like query to retrieve two columns. The first column is the plain "a.x" field, and the second is a String of a comma separated list of all of the a.y.z.v values. If this is not possible, then having the second column return as a Java list of the a.y.z.v values would be satisfactory.
In short, I would like to flatten the a.y.z.v collection to a csv String or to a List object from inside the query.
I have already attempted the following:
Using the "new" keyword in a list subselect. ie, "select a.x, (select new list(a.y.z.v)) from a". If necessary I could have transformed the contents of the list into a csv, but this caused a syntax error.
Using the "new" keyword with a custom object in a subselect. ie, "select a.x, (select new custom.package.ListToCsvObject(a.y.z)) from a". This caused the same error as the first attempt
Using the "elements()" keyword in the select. Unfortunately, this keyword only seems to work inside "in", "exists" clauses (etc), not as the actual returned value.
The only solution we've been able to find was to create a stored procedure in the database and use that, but such a solution is painfully slow through HQL (it turns a sub-second query into a 30 second query) and therefore is not something we want to continue to do.
I am able to make some limited changes to the Hibernate mapping (so I can add #formula, etc) but I would prefer not to have to make major changes to the database schema to support it. (So no, I don't want to create a denormalized "csv_value" column in the database!)
Could anyone suggest some code or, failing that, an alternative approach to solving this problem?
Try something like this should work. Flattening of list to comma separated string is done in the constructor of your VO class. You can also take a look at resultTransformer, you can create a custom resultTransformer and attach it to the query.
class ResultVO {
String x;
String y;
public ResultVO(String x,List<Z> y) {
this.x = x;
this.y = createCSV(y);
}
}
then in HQL
select new ResultVO(a.x,a.y) from a
A warning - this is not a good way to use JPA. If most of your use cases are like this you should seriously reconsider using some other persistence approach (ibastis, spring jdbc template + sql etc).

Categories

Resources