QueryDsl group by with multiple fields - spring

i m trying to include a groupBy in a queryDsl function but i can't come out with an answer.
override fun list(
urlRecords: RecordMap?,
parameters: Parameters,
orderBy: Array<out OrderSpecifier<*>>,
limitOffset: LimitOffset
) = with(dal) {
val selectActions = actions.mapValues { (_, action) ->
action.enabledPredicate(ExpressionType.SELECT)
}
val queryResults = jpaQueryFactory
.from(entityPath)
.apply { joins.forEach { join(it) } }
.apply { leftJoins.forEach { leftJoin(it) } }
.apply(applyJoins)
.select(
QLegameAssistito.legameAssistito.assistito.id,
QLegameAssistito.legameAssistito.inizioValidita,
QLegameAssistito.legameAssistito.fineValidita
)
.apply { if (distinct != null) distinct() }
.where(where(urlRecords), filterWhere(parameters))
.groupBy(QLegameAssistito.legameAssistito.assistito.id,
QLegameAssistito.legameAssistito.inizioValidita,
QLegameAssistito.legameAssistito.fineValidita
)
.orderBy(*orderBy)
.limit(limitOffset.limit)
.offset(limitOffset.offset)
.fetchResults()
ListResults(selectActions, queryResults)
}
Error:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE, found ',' near line 1, column 51 [select count(distinct legameAssistito.assistito.id, legameAssistito.inizioValidita, legameAssistito.fineValidita)
If you take off the groupBy,it works.Also it seems there is a problem is probably in concatenating values in the groupby as it works with just one value.

Related

duplicate result of criteria Api in join query using JpaSpecification

i am new to criteria api, so i have two models: GithubRepository and Issue where GithubReposity has many issue and every issue has one GithubRepository.
I have created many filters but the filter that did not work is the filter for GithubRepository where i want to check if a githubRepository has issues or Not.
after executing and applying has issues unfortunately something wrong happened and i see many duplicates.
here what i did in RepoSpecification:
public Specification<GithubRepository> getReposByIdIn(List<Long> iDs, String repoName) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (repoName != null && !repoName.isEmpty()) {
predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("repositoryName")),
"%" + repoName.toLowerCase() + "%"));
}
if (iDs != null && !iDs.isEmpty()) {
predicates.add( criteriaBuilder.in(root.get("id")).value(iDs) );
}
query.orderBy(criteriaBuilder.asc(root.get("repositoryName")));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
public Specification<GithubRepository> getRepos(Boolean hasIssues,Boolean IsPrivate , String repoName) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (repoName != null && !repoName.isEmpty()) {
predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("repositoryName")),
"%" + repoName.toLowerCase() + "%"));
}
if ( hasIssues!= null && hasIssues.equals(true)) {
// JOINS INSTANCE
Join<GithubRepository, Issue> repoIssueJoin = root.join("issues");
//Predicate predicate = criteriaBuilder.equal(repoIssueJoin.get("githubRepository").get("repositoryName"),
repoName);
//predicates.add(criteriaBuilder.isNotNull(repoIssueJoin));
predicates.add(criteriaBuilder.equal(repoIssueJoin.get("githubRepository"),root));
}
if (IsPrivate != null && IsPrivate.equals(true)) {
predicates.add(criteriaBuilder.equal(root.get("isPrivate"), true));
}
query.orderBy(criteriaBuilder.asc(root.get("repositoryName")));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
}
my problem is in here exactly:
if ( hasIssues!= null && hasIssues.equals(true)) {
// JOINS INSTANCE
Join<GithubRepository, Issue> repoIssueJoin = root.join("issues");
//Predicate predicate = criteriaBuilder.equal(repoIssueJoin.get("githubRepository").get("repositoryName"),
repoName);
//predicates.add(criteriaBuilder.isNotNull(repoIssueJoin));
predicates.add(criteriaBuilder.equal(repoIssueJoin.get("githubRepository"),root));
}
i do not know what is wrong exactly and how to fix the problem but i am stacked with it because i am planning to add a new filter to filter greatOrEqual by number of issues

How to bind oracle params in scala?

i have done of code that it executes any query in scala it works perfect unless if my query has to use same parameter twice. the database version is 12 and the oracle jar is ojdbc6, i wrote this code in order to execute query
def executeQuery(locale: String, query: String, input: Map[String, String], output: List[String]): Vector[Map[String, Any]] = {
var connection: Connection = null;
val properties = ConnectionLoader.getConnectionProperties(locale);
try {
connection = getDBConnection(properties);
val statement = connection prepareCall (query)
if (null != input)
for ((k, v) <- input) {
statement.setObject(k, v)
}
for (k <- output) {
statement.registerOutParameter(k, OracleTypes.INTEGER)
}
val resultSet = statement.executeQuery();
realize(resultSet);
} catch {
case e => throw e;
} finally {
if (null != connection)
connection.close();
}
}
and my query is
SELECT COUNT (1)
FROM ORDERS
WHERE ORDER_ID = :P_ORDER_ID AND STATUS_ID = 4
this query works fine but im getting an error when executing
SELECT COUNT (1)
FROM ORDERS
WHERE ORDER_ID = :P_ORDER_ID AND STATUS_ID = 4 and :P_ORDER_ID=9
Regardless to this unlogical query i'm getting this error
Execution exception[[SQLException: Missing IN or OUT parameter at index:: 2]]
i have googled everything but i got no result please advise

SQLite with swift , i can't get all elements from my table query

I'm new in swift and SQLLite , I had a problem and I didn't know how to fix it
I create table contain [id name Grade] and this is my insert function
let insertStatementString = "INSERT INTO Contact (Id, Name, Grade ) VALUES (?, ?, ?);"
func insert() {
var insertStatement: COpaquePointer = nil
// 1
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
let dic: [NSString] = ["Ray", "Chris", "Martha", "Danielle"]
let grade = [11 , 13 ,11 ,12]
var id = Int32()
for (index, name) in dic.enumerate() {
sqlite3_bind_int(insertStatement, 1, index + 1)
sqlite3_bind_text(insertStatement, 2, name.UTF8String, -1, nil)
sqlite3_bind_int(insertStatement, 3,Int32(grade[index]))
id = id + 1
}
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT statement could not be prepared.")
}
// 5
sqlite3_finalize(insertStatement)
}
insert()
when i call my query function , the while loop work for one time only , but as you can see i had 4 elements in my table
this is my query function
let queryStatementString = "SELECT * FROM Contact;"
func query() {
var queryStatement: COpaquePointer = nil
if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
while (sqlite3_step(queryStatement) == SQLITE_ROW) {
let id = sqlite3_column_int(queryStatement, 0)
let queryResultCol1 = sqlite3_column_text(queryStatement, 1)
let grade = sqlite3_column_int(queryStatement, 2)
let name = String.fromCString(UnsafePointer<CChar>(queryResultCol1))!
print("Query Result:")
print("\(id) | \(name) | \(grade)")
}
} else {
print("SELECT statement could not be prepared")
}
sqlite3_finalize(queryStatement)
}
query()
last thing , this my create Table function
let db = openDatabase()
let createTableString = "CREATE TABLE Contact(" + "Id INT PRIMARY KEY NOT NULL," + "Name CHAR(255)," + "Grade INTEGER)"
func createTable() {
var createTableStatement: COpaquePointer = nil
if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
if sqlite3_step(createTableStatement) == SQLITE_DONE {
print("Contact table created.")
} else {
print("Contact table could not be created.")
}
} else {
print("CREATE TABLE statement could not be prepared.")
}
sqlite3_finalize(createTableStatement)
}
createTable()
In your insert() function, you call sqlite3_step() once. This is why you insert a single row. Move the call to sqlite3_step() inside your loop on names and grades. Also call sqlite3_reset() before setting bindings.

The method 'OrderBy' must be called before the method 'Skip' Exception

I was trying to implement the jQgrid using MvcjQgrid and i got this exception.
System.NotSupportedException was unhandled by user code
Message=The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
Though OrdeyBy is used before Skip method why it is generating the exception? How can it be solved?
I encountered the exception in the controller:
public ActionResult GridDataBasic(GridSettings gridSettings)
{
var jobdescription = sm.GetJobDescription(gridSettings);
var totalJobDescription = sm.CountJobDescription(gridSettings);
var jsonData = new
{
total = totalJobDescription / gridSettings.PageSize + 1,
page = gridSettings.PageIndex,
records = totalJobDescription,
rows = (
from j in jobdescription
select new
{
id = j.JobDescriptionID,
cell = new[]
{
j.JobDescriptionID.ToString(),
j.JobTitle,
j.JobType.JobTypeName,
j.JobPriority.JobPriorityName,
j.JobType.Rate.ToString(),
j.CreationDate.ToShortDateString(),
j.JobDeadline.ToShortDateString(),
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
GetJobDescription Method and CountJobDescription Method
public int CountJobDescription(GridSettings gridSettings)
{
var jobdescription = _dataContext.JobDescriptions.AsQueryable();
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Count();
}
public IQueryable<JobDescription> GetJobDescription(GridSettings gridSettings)
{
var jobdescription = orderJobDescription(_dataContext.JobDescriptions.AsQueryable(), gridSettings.SortColumn, gridSettings.SortOrder);
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Skip((gridSettings.PageIndex - 1) * gridSettings.PageSize).Take(gridSettings.PageSize);
}
And Finally FilterJobDescription and OrderJobDescription
private static IQueryable<JobDescription> FilterJobDescription(IQueryable<JobDescription> jobdescriptions, Rule rule)
{
if (rule.field == "JobDescriptionID")
{
int result;
if (!int.TryParse(rule.data, out result))
return jobdescriptions;
return jobdescriptions.Where(j => j.JobDescriptionID == Convert.ToInt32(rule.data));
}
// Similar Statements
return jobdescriptions;
}
private IQueryable<JobDescription> orderJobDescription(IQueryable<JobDescription> jobdescriptions, string sortColumn, string sortOrder)
{
if (sortColumn == "JobDescriptionID")
return (sortOrder == "desc") ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID) : jobdescriptions.OrderBy(j => j.JobDescriptionID);
return jobdescriptions;
}
The exception means that you always need a sorted input if you apply Skip, also in the case that the user doesn't click on a column to sort by. I could imagine that no sort column is specified when you open the grid view for the first time before the user can even click on a column header. To catch this case I would suggest to define some default sorting that you want when no other sorting criterion is given, for example:
switch (sortColumn)
{
case "JobDescriptionID":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionID)
: jobdescriptions.OrderBy(j => j.JobDescriptionID);
case "JobDescriptionTitle":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionTitle)
: jobdescriptions.OrderBy(j => j.JobDescriptionTitle);
// etc.
default:
return jobdescriptions.OrderBy(j => j.JobDescriptionID);
}
Edit
About your follow-up problems according to your comment: You cannot use ToString() in a LINQ to Entities query. And the next problem would be that you cannot create a string array in a query. I would suggest to load the data from the DB with their native types and then convert afterwards to strings (and to the string array) in memory:
rows = (from j in jobdescription
select new
{
JobDescriptionID = j.JobDescriptionID,
JobTitle = j.JobTitle,
JobTypeName = j.JobType.JobTypeName,
JobPriorityName = j.JobPriority.JobPriorityName,
Rate = j.JobType.Rate,
CreationDate = j.CreationDate,
JobDeadline = j.JobDeadline
})
.AsEnumerable() // DB query runs here, the rest is in memory
.Select(a => new
{
id = a.JobDescriptionID,
cell = new[]
{
a.JobDescriptionID.ToString(),
a.JobTitle,
a.JobTypeName,
a.JobPriorityName,
a.Rate.ToString(),
a.CreationDate.ToShortDateString(),
a.JobDeadline.ToShortDateString()
}
})
.ToArray()
I had the same type of problem after sorting using some code from Adam Anderson that accepted a generic sort string in OrderBy.
After getting this excpetion, i did lots of research and found that very clever fix:
var query = SelectOrders(companyNo, sortExpression);
return Queryable.Skip(query, iStartRow).Take(iPageSize).ToList();
Hope that helps !
SP

Dynamically Set Column Name In LINQ Query

Im trying to write a method which will allow me to search different DataTables, over different columns.
So far i have the following:
string selectedValue;
string searchColumn;
string targetColumn;
var results = (from a in dt.AsEnumerable()
where a.Field<string>(searchColumn) == selectedValue
select new
{
targetColumn = a.Field<string>(targetColumn)
}).Distinct();
Which kind of gets the job done, but I'm left with the column name as targetColumn rather than the actual column name I want.
Is there any way to resolve this?
Thanks in advance
CM
I make a LINQ to Datatables
public List<DataRow> Where(this DataTable dt, Func<DataRow, bool> pred)
{
List<DataRow> res = new List<DataRow>();
try {
if (dt != null && dt.Rows.Count > 0) {
for (i = 0; i <= dt.Rows.Count - 1; i++) {
if (pred(dt(i))) {
res.Add(dt(i));
}
}
}
} catch (Exception ex) {
PromptMsg(ex);
}
return res;
}
Usage :
var RowsList = dt.Where(f => f("SomeField").toString() == "SomeValue" ||
f("OtherField") > 5);

Resources