Between in createdCriteria not works - java

I have a very strange problem. I create 3 entities with the following data:
CCB ccb1 = new Ccb(1)
CCB ccb2 = new Ccb(2)
CCB ccb3 = new Ccb(3)
Where the parameter (Long) is the object id.
Then, when wanting to create a list with the between clause, it is created with size = 0:
ConcurrentLinkedQueue<Long> ccbIds = new ConcurrentLinkedQueue(
Ccb.createCriteria().list {
between("id", 1, 5)
projections {
id()
}
}
)
I've tried this alternative and it doesn't work either:
ConcurrentLinkedQueue<Long> ccbIds = new ConcurrentLinkedQueue(
Ccb.createCriteria().list {
between("id", "1", "5")
projections {
id()
}
}
)
The incredible thing is that if I replace the between with the eq:
ConcurrentLinkedQueue<Long> ccbIds = new ConcurrentLinkedQueue(
Ccb.createCriteria().list {
eq("id", 2)
projections {
id()
}
}
)
Now the list returns me the element with id 2!
I can't understand where is the error.
Thanks!
EDIT:
Config of DataSource.groovy:
dataSource {
dbCreate = "create-drop"
driverClassName = "org.h2.Driver"
dialect = "org.hibernate.dialect.H2Dialect"
url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
}

try this:
Ccb.createCriteria().list {
between("id", 1l, 5l)
projections {
property('id')
}
}
or:
Ccb.createCriteria().list {
and{
between("id", 1l, 5l)
}
projections {
property('id')
}
}

Can't you stream the list and filter by ID?
def list = foolist.stream().filter(f -> f.getId() > 0 && f.getId() < 4).collect(Collectors.toList())

After run different tests, I came to the conclusion that it is a bug in Grails when using the H2 storage. With SQL it works fine.

Related

Filter and Count Items in List inside a For Loop | Kotlin

Hey guys I switched from Swift to Kotlin a few days ago and I'm trying to implement a similar function I have in swift into kotlin and failing
Here is what I'm doing in swift
private var issues: [PathPmCore.Issue] = [] {
didSet {
AppState.shared.issues = issues
taskModels.removeAll()
var models = [ListModel]()
var components = [Double]()
for status in TaskState.allCases {
let count = issues.filter({ isssue in
status.ids.contains(where: { statusId in
statusId == isssue.status.currentStatus.id
})
}).count
models.append(.init(activeTasks: .constant(count), circleState: .constant(status)))
components.append(Double(count))
}
DispatchQueue.main.async {
self.taskModels = models
self.chartComponents = components
}
}
The way I approached it in Kotlin is similar
private var issues: List<Issues> = emptyList()
set(value: List<Issues>){
for (status in TaskState.values()) {
val models: ArrayList<ListModel> = arrayListOf<ListModel>()
val components = listOf<Double>()
val count = issues.filterNotNull().forEach { issue ->
status.ids.find { statusId ->
statusId == issue.status.currentStatus.id
}
}
println(count)
value.count()
}
}
It works, with no errors but the one setter in Kotlin returns an empty array/list.
Why it's empty
It's empty because you are not setting the backing field !
Possible Solution (maybe)
So, if I understood right what you are trying to achieve, here is a possible solution for your problem
private var issues: List<Issues> = emptyList()
set(value: List<Issues>){
field = TaskState.values().map {
issues.filterNotNull().filter { issue ->
it.ids.any { statusId ->
statusId == issue.status.currentStatus.id
}
}
}.flatten()
}
I removed models and components because you are not using them.

Why CustomProjectAggregationOperation Not working in SpringMongoTemplate

I trying the following query in spring onto the template, that query works in Mongoserver, but when I using the query in the SpringMongo template, the filter does not work, it gets all date, instead of filters date. If anyone knows this issue. pls, help me out this.
The Native Mongo Query:-
db.Task_Status.aggregate([{
{"$addFields":{"timeDiff": { $floor: { $divide: [ { $subtract:[ new Date() , "$currenttime" ] } , 60000 ] } } }},
{$match:{$and:[{"timeDiff":{"$lt": 12}}]}} }]);
The Spring MongoTempalte java Code:
String nativeFilterQuery = "{\"$addFields\":{\"timeDiff\": { $floor: { $divide: [ { $subtract:[ new Date() , \"$currenttime\" ] } , 60000 ] } } }},{$match:{$and:[{\"timeDiff\":{\"$lt\": 12}}]}}";
List<TaskStatus> amTaskLists = Collections.EMPTY_LIST;
List<AggregationOperation> aggregationOperations = new ArrayList<>();
if (StringUtility.isNotNullOrEmpty(nativeFilterQuery)) {
aggregationOperations.add(new CustomProjectAggregationOperation(nativeFilterQuery));
}
TypedAggregation<TaskStatus> aggregation = Aggregation.newAggregation(TaskStatus.class, aggregationOperations);
AggregationResults result = execute(aggregation, TaskStatus.class);
amTaskLists = result.getMappedResults();
When I split the query and Run like following its works
String queryOne = "{\"$addFields\":{\"timeDiff\": { $floor: { $divide: [ { $subtract:[ new Date() , \"$currenttime\" ] } , 60000 ] } } }}";
String queryTwo = "{$match:{$and:[{\"timeDiff\":{\"$lt\": 12}}]}}";
List<AggregationOperation> aggregationOperations = new ArrayList<>();
if (StringUtility.isNotNullOrEmpty(queryOne)) {
aggregationOperations.add(new CustomProjectAggregationOperation(queryOne));
}
if (StringUtility.isNotNullOrEmpty(queryTwo)) {
aggregationOperations.add(new CustomProjectAggregationOperation(queryTwo));
}
You can use AggregationOperation for performing different aggregation in springmongo,but $addFields not support till 3.2 version for that use DBObject for creating query.
For example i used addFields to add score in textcriria my AggregationOperation is:
AggregationOperation score = new AggregationOperation() {
#Override
public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
return new BasicDBObject(
"$addFields",
new BasicDBObject("score", new BasicDBObject("$meta","textScore"))
);
}
};
So you can use in your way to find timeDiff and also create match function and you can use like:
List<AggregationOperation> dataListopeartion = new ArrayList<>();
MatchOperation match = new MatchOperation(new Criteria().andOperator(Criteria.where("timeDiff").lte(12));
dataListopeartion.add(match);
dataListopeartion.add(score); //your timeDiff query with AggregationOperation
Aggregation agg = Aggregation.newAggregation(dataListopeartion);
AggregationResults<TaskStatus> groupResults = mongoTemplate.aggregate(agg, Task_Status,TaskStatus.class);
ListMongoWrapper<TaskStatus> mongoWrapper = groupResults.getMappedResults();
You can also refer following answer of SO for better understanding:
link1, link2

BIRT: How to remove a dataset parameter programmatically

I want to modify an existing *.rptdesign file and save it under a new name.
The existing file contains a Data Set with a template SQL select statement and several DS parameters.
I'd like to use an actual SQL select statement which uses only part of the DS parameters.
However, the following code results in the exception:
Exception in thread "main" `java.lang.RuntimeException`: *The structure is floating, and its handle is invalid!*
at org.eclipse.birt.report.model.api.StructureHandle.getStringProperty(StructureHandle.java:207)
at org.eclipse.birt.report.model.api.DataSetParameterHandle.getName(DataSetParameterHandle.java:143)
at org.eclipse.birt.report.model.api.DataSetHandle$DataSetParametersPropertyHandle.removeParamBindingsFor(DataSetHandle.java:851)
at org.eclipse.birt.report.model.api.DataSetHandle$DataSetParametersPropertyHandle.removeItems(DataSetHandle.java:694)
--
OdaDataSetHandle dsMaster = (OdaDataSetHandle) report.findDataSet("Master");
HashSet<String> bindVarsUsed = new HashSet<String>();
...
// find out which DS parameters are actually used
HashSet<String> bindVarsUsed = new HashSet<String>();
...
ArrayList<OdaDataSetParameterHandle> toRemove = new ArrayList<OdaDataSetParameterHandle>();
for (Iterator iter = dsMaster.parametersIterator(); iter.hasNext(); ) {
OdaDataSetParameterHandle dsPara = (OdaDataSetParameterHandle)iter.next();
String name = dsPara.getName();
if (name.startsWith("param_")) {
String bindVarName = name.substring(6);
if (!bindVarsUsed.contains(bindVarName)) {
toRemove.add(dsPara);
}
}
}
PropertyHandle paramsHandle = dsMaster.getPropertyHandle( OdaDataSetHandle.PARAMETERS_PROP );
paramsHandle.removeItems(toRemove);
What is wrong here?
Has anyone used the DE API to remove parameters from an existing Data Set?
I had similar issue. Resolved it by calling 'removeItem' multiple times and also had to re-evaluate parametersIterator everytime.
protected void updateDataSetParameters(OdaDataSetHandle dataSetHandle) throws SemanticException {
int countMatches = StringUtils.countMatches(dataSetHandle.getQueryText(), "?");
int paramIndex = 0;
do {
paramIndex = 0;
PropertyHandle odaDataSetParameterProp = dataSetHandle.getPropertyHandle(OdaDataSetHandle.PARAMETERS_PROP);
Iterator parametersIterator = dataSetHandle.parametersIterator();
while(parametersIterator.hasNext()) {
Object next = parametersIterator.next();
paramIndex++;
if(paramIndex > countMatches) {
odaDataSetParameterProp.removeItem(next);
break;
}
}
if(paramIndex < countMatches) {
paramIndex++;
OdaDataSetParameter dataSetParameter = createDataSetParameter(paramIndex);
odaDataSetParameterProp.addItem(dataSetParameter);
}
} while(countMatches != paramIndex);
}
private OdaDataSetParameter createDataSetParameter(int paramIndex) {
OdaDataSetParameter dataSetParameter = StructureFactory.createOdaDataSetParameter();
dataSetParameter.setName("param_" + paramIndex);
dataSetParameter.setDataType(DesignChoiceConstants.PARAM_TYPE_INTEGER);
dataSetParameter.setNativeDataType(1);
dataSetParameter.setPosition(paramIndex);
dataSetParameter.setIsInput(true);
dataSetParameter.setIsOutput(false);
dataSetParameter.setExpressionProperty("defaultValue", new Expression("<evaluation script>", ExpressionType.JAVASCRIPT));
return dataSetParameter;
}

Complex query in Morphia

in my method Java,
I would like to pass as a parameter to my collection MongoDB a complex query like this one:
{"$or": [{"$and": [{"contextID": "AKKA"}, {"messageID": "PIPPO"}]},
{"$and": [{"domain": "Niguarda"}, {"hostName": {"$ne": "hostServer"}}]}
]
}
The string that contains the query is variable and passed as parameter in query string.
I tried to pass the query as parameter to method criteria
(queryDB.criteria("
{"$or": [
{"$and": [{"contextID": "AKKA"}, {"messageID": "PIPPO"}]},
{"$and": [{"domain": "Niguarda"}, {"hostName": {"$ne": "hostServer"}}]}]
}"
)
but it does not work.
Any suggestions?
What you're trying to do would be
Query q = dao.createQuery();
q.or(
q.and(new Criteria[]{ dao.createQuery().filter("contextID").equal("AKKA"),
dao.createQuery().filter("messageID").equal("PIPPO") }),
q.and(new Criteria[]{ dao.createQuery().filter("domain").equal("Niguarda"),
dao.createQuery().filter("hostname").notEqual("hostServer") })
);
This is now the code (it's works fine but I abandoned morphia):
public long count(String query) throws Exception {
DB db = mongoClient.getDB(mongoDBName);
DBCollection dbCollection = db.getCollection(mongoDBCollection);
DBObject dbObjQuery;
long l = 0;
try {
if (!(query == null)) {
dbObjQuery = (DBObject) JSON.parse(query);
l = dbCollection.find(dbObjQuery).count();
} else {
l = dbCollection.find().count();
}
} catch (Exception e) {
} finally {
}
return l;
}
There is another way to do this with morphia?

Hibernate order by with nulls last

Hibernate used with PostgreSQL DB while ordering desc by a column puts null values higher than not null ones.
SQL99 standard offers keyword "NULLS LAST" to declare that null values should be put lower than not nulls.
Can "NULLS LAST" behaviour be achieved using Hibernate's Criteria API?
This feature has been implemented during Hibernate 4.2.x and 4.3.x releases as previously mentioned.
It can be used as for example:
Criteria criteria = ...;
criteria.addOrder( Order.desc( "name" ).nulls(NullPrecedence.FIRST) );
Hibernate v4.3 javadocs are less omissive here.
Given that HHH-465 is not fixed and is not going to get fixed in a near future for the reasons given by Steve Ebersole, your best option would be to use the CustomNullsFirstInterceptor attached to the issue either globally or specifically to alter the SQL statement.
I'm posting it below for the readers (credits to Emilio Dolce):
public class CustomNullsFirstInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = -3156853534261313031L;
private static final String ORDER_BY_TOKEN = "order by";
public String onPrepareStatement(String sql) {
int orderByStart = sql.toLowerCase().indexOf(ORDER_BY_TOKEN);
if (orderByStart == -1) {
return super.onPrepareStatement(sql);
}
orderByStart += ORDER_BY_TOKEN.length() + 1;
int orderByEnd = sql.indexOf(")", orderByStart);
if (orderByEnd == -1) {
orderByEnd = sql.indexOf(" UNION ", orderByStart);
if (orderByEnd == -1) {
orderByEnd = sql.length();
}
}
String orderByContent = sql.substring(orderByStart, orderByEnd);
String[] orderByNames = orderByContent.split("\\,");
for (int i=0; i<orderByNames.length; i++) {
if (orderByNames[i].trim().length() > 0) {
if (orderByNames[i].trim().toLowerCase().endsWith("desc")) {
orderByNames[i] += " NULLS LAST";
} else {
orderByNames[i] += " NULLS FIRST";
}
}
}
orderByContent = StringUtils.join(orderByNames, ",");
sql = sql.substring(0, orderByStart) + orderByContent + sql.substring(orderByEnd);
return super.onPrepareStatement(sql);
}
}
You can configure "nulls first" / "nulls last" in hibernate properties so it will be picked up by any criteria call by default: hibernate.order_by.default_null_ordering=last (or =first).
See this hibernate commit for details.
We can create Pageable object with following Sort parameter:
JpaSort.unsafe(Sort.Direction.ASC, "ISNULL(column_name), (column_name)")
We can prepare HQL as well:
String hql = "FROM EntityName e ORDER BY e.columnName NULLS LAST";
Here's my update to the class by (Pascal Thivent):
for (int i = 0; i < orderByNames.length; i++) {
if (orderByNames[i].trim().length() > 0) {
String orderName = orderByNames[i].trim().toLowerCase();
if (orderName.contains("desc")) {
orderByNames[i] = orderName.replace("desc", "desc NULLS LAST");
} else {
orderByNames[i] = orderName.replace("asc", "asc NULLS FIRST");
}
}
}
This fixes the problem:
This breaks if sql has limit/offset after order by – Sathish Apr 1 '11 at 14:52
Also here's how you can use this within JPA (hibernate):
Session session = entityManager.unwrap(Session.class);
Session nullsSortingProperlySession = null;
try {
// perform a query guaranteeing that nulls will sort last
nullsSortingProperlySession = session.getSessionFactory().withOptions()
.interceptor(new GuaranteeNullsFirstInterceptor())
.openSession();
} finally {
// release the session, or the db connections will spiral
try {
if (nullsSortingProperlySession != null) {
nullsSortingProperlySession.close();
}
} catch (Exception e) {
logger.error("Error closing session", e);
}
}
I've tested this on postgres and it fixes the 'nulls are higher than non-nulls' issue that we were having.
Another variant, if you create SQL on the fly and don't use Criteria API:
ORDER BY COALESCE(,'0') [ASC|DESC]
This works either for varchar or numeric columns.
For future travellers... I solved this by overriding the Hibernate dialect. I needed to add null first for asc and null last for desc by default in CriteriaQuery, which is for some reason not supported. (It's supported in legacy CriteriaAPI)
package io.tolgee.dialects.postgres
import org.hibernate.NullPrecedence
import org.hibernate.dialect.PostgreSQL10Dialect
#Suppress("unused")
class CustomPostgreSQLDialect : PostgreSQL10Dialect() {
override fun renderOrderByElement(expression: String?, collation: String?, order: String?, nulls: NullPrecedence?): String {
if (nulls == NullPrecedence.NONE) {
if (order == "asc") {
return super.renderOrderByElement(expression, collation, order, NullPrecedence.FIRST)
}
if (order == "desc") {
return super.renderOrderByElement(expression, collation, order, NullPrecedence.LAST)
}
}
return super.renderOrderByElement(expression, collation, order, nulls)
}
}
There appears to be a change request/bug ticket open for this

Categories