sql criteria with count function aliasToBean issue Hibernate - java

In my sql i have used count function like
COUNT( bip.seat_number) as totalSeats
Im trying to map this totalSeats attribute to a java bean called ScheduleSummery
Transformers.aliasToBean(ScheduleSummery.class)
Here is my java bean class
public class ScheduleSummery {
private String totalSeats;
public String getTotalSeats() {
return totalSeats;
}
public void setTotalSeats(String totalSeats) {
this.totalSeats = totalSeats;
}
}
Im getting below exception when trying to run this code. I have defined totalSeats as a String but it still shows expected type as java.lang.String
IllegalArgumentException occurred while calling setter for property
[ScheduleSummery.totalSeats
(expected type = java.lang.String)];
target = [ScheduleSummery#3f08662f], property value = [27]
any idea ? :(

The problem is your query returns some kind of number and your property is expecting a String.
You have to options
convert the result of the query to a String like so (should work with Oracle, the precise syntax for other databases might vary):
to_char(COUNT( bip.seat_number)) as totalSeats
change the property to the type you are getting out of the sql statement. You already tried int (according to other, now deleted answers. Other options you might try are: long, Long, Integer, BigInteger If try and error doesn't help, you can determine where in the code Hibernate tries the assignement (from the stacktrace), put a breakpoint there and see, what kind of value it actually has.

Related

I want to retrieve the stored DB value converted to a string list in spring boot

I want to retrieve the stored DB value converted to a string list in spring boot.
As an entity in Spring Boot, I wanted to process it like this, so I processed it as an array that was converted to a string.
#Column(name = "keyword")
#Convert(converter = StringListConverter.class)
private List<String> keyword;
The problem is that when I do a search, I get an error. For reference, I am calling with restapi and using postgresql and jpa.
And the search used sql criteria. (If you let us know by query dsl, we will implement it in that way.)
(Values and keys belonging to the keywords below are entered normally.)
Expression<String> delimiter = criteriaBuilder.<String>literal(",");
Expression<String> sqlFunction = criteriaBuilder.function("array_to_string",String.class,root.get(entry.getKey()), delimiter);
predicates.add(criteriaBuilder.like(sqlFunction,
'%' + entry.getValue().toString().toLowerCase() + '%'));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
I googled and created a search logic in this format, but I get an error. Retrieval of any type other than an array is error-free.
Array search feels very difficult.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessResourceUsageException: JDBC exception executing SQL [select m1_0.id,m1_0.created,m1_0.description,m1_0.disable,m1_0.group_id,m1_0.keyword,m1_0.name,m1_0.updated,m1_0.work from member m1_0 where array_to_string(m1_0.keyword,',') like ? escape '' order by m1_0.id desc offset ? rows fetch first ? rows only]; SQL [n/a]] with root cause
org.postgresql.util.PSQLException: ERROR: function array_to_string(character varying, unknown) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts. Position: 174
I would appreciate it if you could tell me how to do it, a simple example or something to refer to.
What I'm trying to do is, once I get a string value, I want to start by searching to see if that string is in the array.
I've been struggling for a long time and haven't been able to find an answer, so I'm asking this question. I also don't quite understand what the error means.

Insert a new record with autogenerated id

I am trying to insert a new record into a simple database table with MyBatis but I get a strange exception. Mybe it is related to that I am not using POJO.
MyBatis version: 3.4.5
My table:
CREATE TABLE IF NOT EXISTS image
(
id BIGINT PRIMARY KEY,
content BYTEA
) WITHOUT OIDS;
MyBatis mapper:
#Insert("INSERT INTO image (id, content) VALUES (#{id}, #{content})")
#SelectKey(statement = "SELECT NEXTVAL('image_seq')", keyProperty = "id", before = true, resultType = long.class)
long insertImage(byte[] content);
The way I am trying to use it:
byte[] fileContent = IOUtils.toByteArray(inputStream);
long id = imageDao.insertImage(fileContent);
The exception what I get:
java.lang.ClassCastException: java.lang.Long cannot be cast to [B
at org.apache.ibatis.type.ByteArrayTypeHandler.setNonNullParameter(ByteArrayTypeHandler.java:26)
at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:53)
at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:93)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:86)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
I do not want to create POJO class with getter/setter method for this one "content" param but I think this issue is related to missing POJO.
What is the solution?
EDIT
I am trying to debug mybatis code and I have found "[B" in the parameterTypes:
#SelectKey is useful when you want to reuse generated value farther in the code, but it seems yo will not.
Then why not keep everything in the SQL:
INSERT INTO image (id, content) VALUES ((SELECT NEXTVAL('image_seq')), #{content})
For exception regarding parameters, parameters must be named with #Param annotation
int insertImage(#Param("content") byte[] content);
or
int insertImage(#Param("id) Long id, #Param("content") byte[] content)
Note that INSERT as well as UPDATE and DELETE statements returns type int being the number of inserted/updated/deleted rows, [...]
EDIT: unless you consider that under the hood, the java 8 PreparedStatement.executeLargeUpdate returning long is executed.
[...] and not the generated key as it is suggested. Then it seems you eventually want to get the key value, that means back to square one with #SelectKey and need for a POJO and a target property for the generated value. It even works with bulk insert with generated keys.
I have discovered lately that actual parameters name can be used (then your code will work as is) if following instructions in settings section of the documentation:
useActualParamName Allow referencing statement parameters by their
actual names declared in the method signature. To use this feature,
your project must be compiled in Java 8 with -parameters option.
(Since: 3.4.1) valid values: true | false default: true
java.lang.Long cannot be cast to [B
This is saying that you are trying to convert long to byte[]
Looking at source of org.apache.ibatis.type.ByteArrayTypeHandler:
public void setNonNullParameter(PreparedStatement ps, int i, byte[] parameter, JdbcType jdbcType) throws SQLException {
ps.setBytes(i, parameter);
}
I think you need to remove {id} from insert annotation (as this value is autogenerated).
#Insert("INSERT INTO image (content) VALUES (#{content})")
Otherwise parameters are shifted by one.

How to check equality of spark columns after renaming

I am trying to write some tests for a Java Spark-Sql application. One operation I need to test renames a column, and I ran into some difficulty comparing the actual value of the renamed column with my expected value. After some experimentation, I was able to write the following two tests to demonstrate the problem:
First, as a sanity check, I tried this (df is a spark sql DataFrame, generated by reading some sample data from a json file I'm testing against):
#Test
public void testColumnEquality() throws Exception {
Column val1 = df.col("col2");
Column val2 = df.col("col2");
Assert.assertEquals(val1, val2);
}
Which passes, as one would expect. Then I tried this:
#Test
public void testReanmeColumnEquality() throws Exception {
Column val1 = df.col("col2").as("col2");
Column val2 = df.col("col2").as("col2");
Assert.assertEquals(val1, val2);
}
which fails with the error java.lang.AssertionError: expected:<col2 AS col2#4L> but was:<col2 AS col2#5L>
Digging around in the scala code (full disclosure - I know very little scala) it looks like this has to do with the NamedExpression unique id.
Is there any way to sensibly check that these two columns represent the same operations with the same alias?
(I'm working in spark 1.6, and would ideally like a solution for that version line, but if this is fixed in 2.0 that would also be good information.)
Thanks you.
I wrote a blog post about how to resolve this:
The trick is: check whether the Expression has the Alias trait:
`column.expr() instanceof Alias`
If it does, unpack the child expression and the name using the Extractor pattern:
alias = (Alias) column.expr()
Option<Tuple2<Expression, String>> aliasTuple = Alias$.MODULE$.unapply(alias);
I did some digging and it looks like the information about the child of a Column with an alias is lost in the process of instantiating the new Column. Maybe there is a state to query somewhere, but I didn't find it.
So it's not an answer, but hopefully it is useful or of interest to somebody.
more info
The definition of the as method on a Column object refers to the name function (see Column.scala), which just call the Alias case class defined here. The Alias (with its child), is not exposed. It is directly given to the Column class withExpr function which instantiate a new column based on the Alias named expression.
So you either compare directly the result of toString on the columns (loosing the information on where the column comes from, i.e. which dataframe), or you actually parse the string printed by the explain(true) method...but it doesn't seem sensible to me...

Converting an ActiveRecord:Relation to java array

I am running a 'where' query which is running on a table MyTable in my rails application.
I want to convert the results of a specific column from this query(ActiveRecord::Relation) to Java Array of String type.
This is what I am doing :
employeesJavaArray=MyTable.where("salary = ?",100).pluck(:columnName).to_java(java.lang.String)
However I am receiving this error in my logs :-
TypeError (could not coerce Fixnum to class java.lang.String):
Can you please help me out what could be wrong with the statement that I have written.
I would ensure that the array only includes string (by calling to_s) first:
employeesJavaArray = MyTable.where("salary = ?",100)
.pluck(:columnName)
.map(&:to_s)
.to_java(java.lang.String)

DATEDIFF not working in JAVA

Am running a query from JAVA , the query contains DATEDIFF function in which the parameter is a keyword,we can give yy,mm,day,etc.. so am getting these keyword from user as parameter and setting it in query, but the issue is it wont execute, it gives an exception as Invalid parameter for argument 1. If i run the same query in CLIENT it gives result, but if i give quotes to keyword like 'day' it gives the same error in CLIENT also. So my question how will I set it in the query from JAVA. Currently am doing like
for (String param : params) {
try {
namedParameterStatement.setObject(param,requiredFilterValues.get(param));
} catch (RuntimeException e) {
}
}
This is the query am using
SELECT CUST_KEY,Eff_Date_From,Eff_Date_To, DATEDIFF(:intervals,Eff_Date_From,Eff_Date_To) as datediffs,Active FROM CUSTOMER_DIM WHERE Active = :active
Am passing values for params intervalsand active, The issue is with :intervals as it takes keywords.
I think the java program setting the parameter as string that is why its generating error.. How can i implement this?
The problem is that you can only pass values using parametrized queries. You can't pass keywords (nor object names). In the case of your query. they would be passed as the equivalent of DATEDIFF('<your-keyword>', .., which wouldn't work either.
There is no solution except manually concatenating the required keyword into the query, or creating a convoluted query using a CASE-construct to get the right value depending on the value passed:
case ? when 'MONTH' then datediffer(MONTH, ..) when .. end
You may need to explicitly cast the parameter to a VARCHAR to get it to work.

Categories