Retrieving a one to many Map on an entity using HQL - hql

I have a class called Product which has the following Map on it:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#MapKeyEnumerated(EnumType.STRING)
private Map<SampleType, Sample<?>> samples = new BasicMap<SampleType, Sample<?>>();
I want to write an HQL query to get the map itself along with some other fields on the Product.
I tried the following:
SELECT product.id, product.name, index(sample), sample
FROM Product p INNER JOIN p.samples sample
But the above returns duplicate rows for Product and each entry in the map.
For example, if it looks like:
Product1 - {{SampleType1, Sample1}{SampleType2, Sample2}}
It returns 2 rows:
001, Product1, SampleType1, Sample1
001, Product1, SampleType2, Sample2
Instead, it should return something like:
001, Product1,{{SampleType1, Sample1}{SampleType2, Sample2}}
Thanks!

Related

JPA find first by created in given list

I have a model class which has these fields:
class Student {
Long roleNo;
Long version;
Date createdAt;
Date updateAt;
}
Now I'm trying to write a JPA query in which I can pass a list of role numbers and for every role number I can get a latest record by version.
I tried to do this but I'm only getting one record:
findFirstByRoleNoIn(List<Long> roleNo);
One way is to make use of #Query annotation to write simple query. Sample query for your case:
#Query(nativeQuery = true, value = """
SELECT s.* FROM student s
INNER JOIN (SELECT
role_no,
MAX(version) AS latest
FROM student GROUP BY role_no) t_version
ON s.role_no = t_version.role_no
AND s.version = t_version.latest
WHERE s.role_no IN (:roleNo)
""")
findLatestVersion(#Param("roleNo") List<Long> roleNo);

Room database: how to retrieve column names into list of strings?

I have a Room table named "addresses" with 15 columns. I retrieve one row and want to get values into List< String >, not List< Addresses >. Is that possible?
#Query("SELECT * FROM addresses WHERE myid= :id")
List<String> getAddressAsList(int id);
Moreover, is it possible to retrieve database table column names together with values into list of map <"column name","value"> like this?
#Query("SELECT * FROM addresses WHERE myid= :id")
List<Map<String, String> getAddressAsList(int id);
You can use a SupportSQLiteDatabase but not a Dao.
Say you have, in an activity,
db = yourRoomDatabase.getInstance(this);
i.e. you'd typically then use something like yourDao = db.getYourDao(); and then
myAddressList = dao.getAddressList();
You can then do:-
SupportSQLiteDatabase sdb = db.getOpenHelper().getWritableDatabase();
Cursor csr = sdb.query("SELECT * FROM address WHERE myid=?",new String[]{String.value(id)}
Then to get the list of column names in the Cursor you can use:-
val columnNames = csr.columnNames
To get the Map of columnnames and values you could use :-
val columnsAndValues: MutableMap<String,String> = mutableMapOf()
while (csr.moveToNext()) {
for (i: Int in 0..csr.columnCount) {
columnsAndValues.put(csr.columnNames.get(i),csr.getString(i))
}
}
csr.close()

QueryDSL Paging Sorting duplicates

I have got an Entity A say Car with a OneToMany relationship to an Entity B say CarProperty.
My Car Repository extends QueryDslPredicateExecutor to support paging and sorting:
Page<T> findAll(Predicate predicate, Pageable pageable);
I'm trying to execute a query where I sort the results, by a column of CarProperty, defining the sort on pageable variable.
However since it is a One To Many relationship between Car and CarProperty, I have returned duplicates of Car.
Is it possible to obtain distinct results on Car using this structure?
If it is not possible to use distinct on the Predicate, how could I represent the following query in the predicate (using exists to eliminate duplicates):
SELECT Car.*
FROM Car C LEFT JOIN CarProperty CP ON (C.ID = CP.CAR_ID)
WHERE EXISTS (SELECT 1
FROM CarProperty CP2
WHERE CP2.CAR_ID = C.ID AND CP2.ID = CP.ID)
ORDER BY CP.PROPERTY_NAME ASC;
Thanks in advance
You can use named entity graph to avoid duplicate records, in my case it worked.
#NamedEntityGraph(name = "Car.carProperty" ,attributeNodes = #NamedAttributeNode("carProperties"))
#Entity
public class Car {
#OneToMany
#JoinColumn(name = "carProperties")
private List<CarProperty> carProperties;
}
and then override findall method
#EntityGraph(value = "Car.carProperty" , type = EntityGraphType.LOAD)
Page<Car> findAll(Predicate predicate, Pageable pageable);

PIG: Select records from a relaltion only if it is present in another relation

I have the following data set for a movie database:
Ratings: UserID, MovieID, Rating
Movies: MovieID, Genre
I filtered out the movies with Genres as "Action" or "War" using:
movie_filter = filter Movies by (genre matches '.*Action.*') OR (genre matches '.*War.*');
Now, I have to calculate the average ratings for War or Action movies. But the ratings is present in the Ratings file. To do this, I use the query:
movie_groups = GROUP movie_filter BY MovieID;
result = FOREACH movie_groups GENERATE Ratings.MovieID, AVG(Ratings.rating);
Then I store the result in a directory location. But when I run the program, I get the following error:
Could not infer the matching function for org.apache.pig.builtin.AVG as multiple or none of them fit. Please use an explicit cast.
Can anyone tell me what I'm doing wrong? Thanks in advance.
It looks like you're missing a join statement, which would join your two data sets (ratings & movies) on the MovieID column. I've mocked up some test data, and provided some example code below.
movie_avg.pig
ratings = LOAD 'movie_ratings.txt' USING PigStorage(',') AS (user_id:chararray, movie_id:chararray, rating:int);
movies = LOAD 'movie_data.txt' USING PigStorage(',') AS (movie_id:chararray,genre:chararray);
movies_filter = FILTER movies BY (genre MATCHES '.*Action.*' OR genre MATCHES '.*War.*');
movies_join = JOIN movies_filter BY movie_id, ratings BY movie_id;
movies_cleanup = FOREACH movies_join GENERATE movies_filter::movie_id AS movie_id, ratings::rating as rating;
movies_group = GROUP movies_cleanup by movie_id;
data = FOREACH movies_group GENERATE group, AVG(movies_cleanup.rating);
dump data;
Output of movie_avg.pig
(Jarhead,3.0)
(Platoon,4.333333333333333)
(Die Hard,3.0)
(Apocolypse Now,4.5)
(Last Action Hero,2.0)
(Lethal Weapon, 4.0)
movie_data.txt
Scrooged,Comedy
Apocolypse Now,War
Platoon,War
Guess Whos Coming To Dinner,Drama
Jarhead,War
Last Action Hero,Action
Die Hard,Action
Lethal Weapon,Action
My Fair Lady,Musical
Frozen,Animation
movie_ratings.txt
12345,Scrooged,4
12345,Frozen,4
12345,My Fair Lady,5
12345,Guess Whos Coming To Dinner,5
12345,Platoon,3
12345,Jarhead,2
23456,Platoon,5
23456,Apocolypse Now,4
23456,Die Hard,3
23456,Last Action Hero,2
34567,Lethal Weapon,4
34567,Jarhead,4
34567,Apocolypse Now,5
34567,Platoon,5
34567,Frozen,5

Subquery nightmares in EF

I'm really, really struggling with what should otherwise be a straightforward query in anything other than LINQ (for example SQL!)
I have two entities:
Product
ProductApprover
The Product entity has a one to many relationship on the ProductApprover entity, e.g:
Product.ProductApprovers gives me all ProductApprover entities relating to the Product.
Getting a Product and associated ProductApprover data is simple enough when querying by my ProductID column on my Product entity as the ProductApprover data associated is bundled into the result automatically, but my problem comes when I want to alter my query by querying data WITHIN my associated ProductApprover entities. I have tried all sorts with use of the 'Where', 'Contains' and 'Any', functions, etc, to perform a subquery, but cannot seem to get the result I want.
The query I want to perform is:
SELECT * FROM Product p
INNER JOIN ProductApprover pa ON p.ProductId = pa.ProductId
WHERE p.ProductId = #id AND pa.Version = #version
Can anybody help me out please? Thank you kindly in advance.
Try this (I guess this is a LINQ interpretation of your SQL query):
int id = 123;
int version = 555;
var results = from p in context.Products
join pa in context.ProductApprovers
on p.ProductId = pa.ProductId
where p.ProductId equals id && pa.Version equals version
select new { Product = p, Approver = pa };
I suspect you want something like this:
var query = from product in db.Products
where product.ProductId == productId
select new {
Product = product,
Approvers = product.Approvers.Where(pa => pa.Version == version)
};
If that doesn't do what you want, could you explain where it falls down?

Resources