I've created this method:
Long getAttributesAfterTimeSent(String x, String y, Long timeSent) {
return repository.countByXAndYAndZTypesAndTimeSentGreaterThanEqual(
x,
y,
new ArrayList<String>() {{ add("attribute1"); add("attribute2"); }},
timeSent);
}
The signature of this method in the repository is as follows:
Long countByXAndYAndZTypesAndTimeSentGreaterThanEqual(String x, String y, Collection<String> attributeTypes, timeSent);
When I run it, i get the following error:
13:18:40.784 [main] INFO o.h.h.i.QueryTranslatorFactoryInitiator - HHH000397: Using ASTQueryTranslatorFactory
13:18:41.014 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1797, SQLState: 42000
13:18:41.014 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - SQL error: 1797 ORA-01797: this operator must be followed by ANY or ALL
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Any pointers?
Figured out the answer.
One of my types was a non-scalar type the: ArrayList.
For cases like this we need to use the IN keyword in the JPA method.
So when changing the method from
countByXAndYAndZTypesAndTimeSentGreaterThanEqual
to
countByXAndYAndZTypesInAndTimeSentGreaterThanEqual
it worked like charm.
This almost certainly has nothing to do with the number of AND phrases in your method.
The limit is only implicit through something like maximum method name length, maximum query length, maximum number of parameters.
It will be way higher than anything any sane person will try to cram in a single method name.
The cause of the exception you are seeing is:
CAUSE:
equal operator = followed by multiple value like (1,2)
This probably means: one of the parameters or maybe some of the attributes is not of scalar type, but some kind of collection or array.
If these leads you toward something you can't easily express through a method name use a #Query annotation and provide the exact query you need to execute.
Related
As result I want to have method with only one string argument (expression A).
But B and C expressions are with same property.
It means 'where date property is null or less_or_equal today'.
So, what I have is this method:
List<EntityObject> findByMyDateIsNullAndMyStringOrMyStringAndMyDateLessThanEqual(Date myDate, String myString);
default List<EntityObject> findByMyDateIsNullAndMyStringOrMyStringAndMyDateLessThanEqual(String myString) {
return findByMyDateIsNullAndMyStringOrMyStringAndMyDateLessThanEqual(Date.valueOf(LocalDate.now()),myString);
}
But, when I try to install in maven, because of test, I get this error:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List MyItemRepository.findByMyDateIsNullAndMyStringOrMyStringAndMyDateLessThanEqual(java.sql.Date,java.lang.String)! null
I know the other way is to use #Query with customized query but I prefer this one.
Is it possible?
My colleague helped me, so...
First of all I forget findAll, because it could be more...
Second of all, I need for date IsLessThanEqual...
And third, I need 3 arguments. Only 3 because one is already defined in method name with 'IsNull'. So, I need 2 string arguments and 1 date argument
List<EntityObject> findAllByMyDateIsNullAndMyStringOrMyStringAndMyDateIsLessThanEqual(Date myDate, String myString1, String myString2);
And then I have to call it with predefined value for date less or equal today date
default List<EntityObject> findAllByMyDateIsNullAndMyStringOrMyStringAndMyDateIsLessThanEqual(String string) {
return findAllByMyDateIsNullAndMyStringOrMyStringAndMyDateIsLessThanEqual(Date.valueOf(LocalDate.now()),string,string);
}
I pass Integer.MIN_VALUE in some Javascript that just returns the input. However, it seems that when I compare the result of the Javascript by using ScriptValueConverter.unwrapValue(returnedObject), the value is the same but the type is a double while I am expecting an integer.
However when I pass Integer.MAX_VALUE in, I do get an integer.
From what I understand, Nashorn uses optimistic type casting so in my eyes, MIN_VALUE can still be an int, there's no need for it to be a double
I suppose that the problem is not Nashorn itself but the javascript code you are running or the third party converter you are using (ScriptValueConverter is neither a javax.script nor a jdk.nashorn class).
I've run the following code:
ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
jsEngine.eval("function identity(x) {return x;}");
System.out.println("Integer.MIN_VALUE:" + ((Invocable) jsEngine).invokeFunction("identity", Integer.MIN_VALUE).getClass());
System.out.println("Integer.MAX_VALUE:" +((Invocable) jsEngine).invokeFunction("identity", Integer.MAX_VALUE).getClass());
and the output is:
Integer.MIN_VALUE: class java.lang.Integer
Integer.MAX_VALUE: class java.lang.Integer
Here you can find a brief explanation about nashorn type conversions.
The reference documentation for the class NSUniqueIdentifier claims that unique ID specifiers are evaluated in the following scheme:
If the container implements a method whose selector matches the relevant valueIn<Key>WithUniqueID: pattern established by scripting
key-value coding, the method is invoked. This method can potentially
be very fast, and it may be relatively easy to implement.
As is the case when evaluating any script object specifier, the container of the specified object is given a chance to evaluate the
object specifier. If the container class implements the
indicesOfObjectsByEvaluatingObjectSpecifier: method, the method is
invoked. This method can potentially be very fast, but it is
relatively difficult to implement.
An NSWhoseSpecifier object that specifies the first object whose relevant 'ID ' attribute matches the ID is synthesized and evaluated.
The NSWhoseSpecifier object must search through all of the keyed
elements in the container, looking for a match. The search is
potentially very slow.
However, I am not seeing valueIn<Key>WithUniqueID: getting called. To give you an example, I have a class where I describe the object specifier in the following way:
- (NSScriptObjectSpecifier *)objectSpecifier
{
assert(self.documentID);
assert(self.controller);
NSScriptObjectSpecifier *containerRef = self.controller.objectSpecifier;
assert(containerRef);
assert(containerRef.keyClassDescription);
return [[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:containerRef.keyClassDescription
containerSpecifier:containerRef
key:#"allObjects"
uniqueID:self.documentID];
}
The method I have defined in the container class is - (id)valueInAllObjectsWithUniqueID:(NSString *)uniqueID is the method I have defined:
- (id)valueInAllObjectsWithUniqueID:(NSString *)uniqueID {
return [self objectWithIdentifier:uniqueID];
}
In the class corresponding to the container I've also overridden -respondsToSelector: to debug this further, and observe that the only relevant method the scripting system queries is indicesOfObjectsByEvaluatingObjectSpecifier: right after -objectSpecifier above is called (and confirmed to return a non-nil result with the container class description and container specifier consistent with the container's class receiving method calls right after the object specifier is evaluated).
Any ideas? This is on OSX Mavericks (10.9.4).
Have a column in a report which a string date field in the format of MM/dd/yyyy. Some of those columns may contain empty strings. Having a problem sorting a section. I am about 10 hours in to telerik reporting so I may be missing something obvious.
I initially tried to use a expression like this:
=IIf(Fields.ExpirationDate='', CDate('1/1/1990'), CDate(Fields.ExpirationDate))
Does that look correct? This threw an error:
An error has occured while processing Report '':
Failed to compare two elements in the array.
------------- InnerException ------------- An error has occured while executing function CDate().
Check InnerException for further
information.
------------- InnerException ------------- Exception has been thrown by the target of an invocation.
------------- InnerException ------------- String was not recognized as a valid DateTime.
Another developer suggested using a custom method so I created inside the report.cs file
public DateTime EmptyDateToNow( string expirationDate )
{
DateTime parsed;
if (!DateTime.TryParse(expirationDate, out parsed))
return DateTime.Now;
return parsed;
}
and then tried to call with =EmptyDateToNow(Fields.ExpirationDate)
and this throws the error:
An error has occured while processing
Report '': Failed to compare two
elements in the array.
------------- InnerException ------------- The expression contains undefined function call
EmptyDateToNow().
public static DateTime EmptyDateToNow( string expirationDate )
I think that Telerik Reporting wants your user functions to be static methods.
I am thinking that the problem with the first approach is that CDate(Fields.ExpirationDate) is being executed even if the expression is true thereby causing the exception to be thrown. You might try something like this to get the desired result without defining a user function:
=CDate(IIf(IsNull(Fields.ExpirationDate) Or Fields.ExpirationDate="", "1/1/1990", Fields.ExpirationDate))
I realize this is a bit old, I just wanted to post in case anyone else is having troubles and searching this.
Make the user function static (and if the call still fails, make the call fully qualified. e.g. =Myclass.EmptyDateToNow(Fields.ExpirationDate)).
Make the function receive an object as a parameter (not a string or any other data type).
Inside the function, check for null and then (it not null) convert to the proper data type and work with it.
I'm formatting a ResultSet to output to a CSV file. As such I really don't care about the Java types of the result set, beyond maybe knowing if it's text or numbers.
Does JDBC guarantee getString will always give a string representation of the values,atleast for single values (I don't need to concern myself about java.sql.Types.ARRAY,java.sql.Types.JAVA_OBJECT and a few others).
e.g. given resultSetMetaData.getColumnType(i) is a Types.FLOAT or a Types.BIGDECIMAL. will rs.GetString(i) always yield some String ?
i.e. Are there cases getString will throw an SQLException or return null when a getXXX would give me the value ?
Yup, check this : http://java.sun.com/docs/books/tutorial/jdbc/basics/retrieving.html
JDBC allows a lot of latitude as far as which getXXX methods you can use to retrieve the different SQL types. For example, the method getInt can be used to retrieve any of the numeric or character types. The data it retrieves will be converted to an int; that is, if the SQL type is VARCHAR , JDBC will attempt to parse an integer out of the VARCHAR. The method getInt is recommended for retrieving only SQL INTEGER types, however, and it cannot be used for the SQL types BINARY, VARBINARY, LONGVARBINARY, DATE , TIME, or TIMESTAMP.
But be careful, different JDBC driver may yield different result.
java.lang.String is a final class - it cannot, ever, have a subclass. So any method that returns String will either return an instance of the class java.lang.String, or a null, or throw an exception.
As for conversion, it is up to the JDBC driver if it will allow you to convert from non-String types. I suspect many will have an issue with it.
I would suggest that you do this instead:
Object item = resultSet.getObject(i);
String strValue = (item == null ? null : item.toString());
That should be more robust, since getObject() will always do the sensible thing.