Named Query with map values in Spring Data JPA - spring

i have a hashmap like which has key value pair such as :
testMap = new HashMap(){{
put(iD, sID);
put(lEVEL, sLevel);
put(tYPE, sType);
put(vALUE, sValue);
Now i have my entity Class which has fields like
#Column(name = "ID")
private String id;
#Column(name = "LEVEL")
private String level;
#Column(name = "PROGRAM")
private String program;
#Column(name = "TYPE")
private String type;
#Column(name = "VALUE")
private String value;
#Column(name = "STARTDATE")
private Date start;
Now i need to form a named query where for each column i have to set values by extracting them from map key value pair (something like this :tesMap.get(iD) and setting in ID column) and also comparing the start date with the current date and setting the largest date in startdate column .
Tried the following using Named query but didn't work .
#Query(value = "SELECT * FROM OVERRIDES s " +
"WHERE s.ID =?1 AND s.LEVEL=?2 AND s.TYPE=?3 AND s.VALUE=?4", nativeQuery = true)
Also ,unable to decide how to compare dates in this select query .

Comparing the dates can be easily done with Date.after() method.
E.g.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = sdf.parse("2022-07-01");
Date date2 = sdf.parse("2022-08-31");
if(date1.after(date2)) {
//set largest date in date column
}
As for the rest question, please provide the whole Entity, or maybe more infos about the query

In SQL, you can compare dates/timestamps with relational operators >, <, >=, <= i.e.
#Query(value = "SELECT * FROM OVERRIDES s " +
"WHERE s.ID =?1 AND s.LEVEL=?2 AND s.TYPE=?3 AND s.VALUE>=?4", nativeQuery = true)

Related

how to extract the today's date out of the date column using SQL query?

I assume I would need to change query in order to sort the data with today's date.
Please tell me how to change it though...
SQL QUERY in ToDoDao
#Query("SELECT * FROM todo_table WHERE date(date) = date('now')")
fun getTodayList(): Flow<List<ToDoTask>>
DATABASE
#Entity(tableName = DATABASE_TABLE)
data class ToDoTask(
#PrimaryKey(autoGenerate = true) val id: Int = 0,
#ColumnInfo(name = "title") val title: String,
#ColumnInfo(name = "description") val description: String,
#ColumnInfo(name = "priority") val priority: Priority,
#ColumnInfo(name = "date") val date: String,
#ColumnInfo(name = "favorite") var favorite: Boolean)
date val in ViewModel class
val date : MutableState<String> = mutableStateOf("")
datas inserted
enter image description here
I have tried the code below and I was able to activate the function as the query as I intented, so I think the query is the issue here.
#Query("SELECT * FROM todo_table WHERE date = '2023-2-14'")
fun getTodayList(): Flow<List<ToDoTask>>
The Issue
The issue is that the SQLite date function expects the date to be in an accepted format.
YYYY-M-DD is not such a format and will result in null rather than a date. YYYY-MM-DD is an accepted format (see https://www.sqlite.org/lang_datefunc.html#time_values). That is leading zeros are used to expand single digit numbers to 2 digit numbers for the month and day of month values.
The Fix (not recommended)
To fix the issue you have shown, you could use (see the However below):-
#Query("SELECT * FROM todo_table WHERE date(substr(date,1,5)||CASE WHEN substr(date,7,1) = '-' THEN '0' ELSE '' END ||substr(date,6)) = date('now');")
If the month was 2 numerics i.e. MM (e.g. 02 for February) then the above would not be necessary.
The CASE WHEN THEN ELSE END construct is similar to IF THEN ELSE END. see https://www.sqlite.org/lang_expr.html#the_case_expression. This is used to add the additional leading 0, when omitted, to the string used by the date function.
However, the above would not cater for days that have the leading 0 omitted for the first 9 days of the month. This due to the 4 permutations of the format (YYYY-MM-DD, YYYY-MM-D, YYYY-M-D and YYYY-M-DD) would be more complex e.g.
#Query("SELECT * FROM todo_table WHERE date(CASE WHEN length(date) = 8 THEN substr(date,1,5)||'0'||substr(date,6,1)||'-0'||substr(date,8) WHEN length(date) = 9 AND substr(date,7,1) = '-' THEN substr(date,1,5)||'0'||substr(date,6) WHEN length(date) = 9 AND substr(date,8,1) = '-' THEN substr(date,1,8)||'0'||substr(date,9) ELSE date END) = date('now');")
Recommended Fix
The recommended fix is to store values using one of the accepted formats rather than try to manipulate values to be an accepted date to then be worked upon using the date and time functions.

Error: Hexadecimal string contains non-hex character for enumerated field

I've got an error
Caused by: org.h2.jdbc.JdbcSQLDataException: Hexadecimal string contains non-hex character: "SWEDISH_MARKET"; SQL statement:
when I pass an enum as parameter to query
Entity has this enum as field.
Field has bellow annotations
#Column(name = "market", nullable = false)
#Enumerated(EnumType.STRING)
private Market type;
query:
#Query(value = "SELECT count(*) " +
"FROM Statements statements WHERE " +
"market = :market",
nativeQuery = true)
long countStatements(#Param("licenseMarket") Market market);
Previously everything was parsed to String and casted in postgres market = (cast :market as text)
Invoking countStatements(Market.SWEDISH_MARKET) throws the exception
You have to use JPQL, then it parse enums automatia
The problem is enum was parsed automatically to the number, regardless column type is text.
Solutions are:
invoke on enum method .name() and pass a param as String,
use SpEL :#{#market?.name()},

Database Oracle, Query Date String JPA Repository Crud Repository, Java 8

NOTE: I can't put some privated code (Database or Java Code).
I have in the Database
CREATE TABLE "SCHEMA"."ENTITY"
(
"HCODFECREGISTR" DATE,
... BLABLA
)
The Entity
import java.util.Date;
public class Entity implements java.io.Serializable {
private Date hcodfecregistr;
....
}
In the Repository Interface
using
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
public interface EntityRepository extends CrudRepository<Entity, Long>,
JpaRepository<Entity, Long> {
public static final String USING_STRING
= " SELECT enti FROM Entity enti WHERE "
+ " (enti.hcodfecregistr BETWEEN TO_DATE(:stringIni,'dd/MM/yyyy hh24:mi') AND TO_DATE(:stringEnd,'dd/MM/yyyy hh24:mi'))";
#Query(value = USING_STRING)
List<Object[]> getEntityUsingString(
#Param("stringIni") String stringIni, #Param("stringEnd") String stringEnd);
public static final String USING_DATE
= " SELECT enti FROM Entity enti WHERE "
+ " (enti.hcodfecregistr BETWEEN :dateIni AND :dateIni) ";
#Query(value = USING_DATE)
List<Object[]> getEntityUsingDate(
#Param("dateIni") Date dateIni, #Param("dateEnd") Date dateEnd);
}
Now I want to perform a query.
Date fecha = //some java.util.Date
Calendar calendar = Calendar.getInstance();
calendar.setTime(fecha);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date dateIni = calendar.getTime();
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
Date dateEnd = calendar.getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
String stringIni = dateFormat.format(fecha) + " 00:00";
String stringEnd = dateFormat.format(fecha) + " 23:59";
Works!
List<Object[]> listaObjects = theRepository.getEntityUsingString(stringIni, stringEnd);
Fails! It does not bring me results (but it also does not show any error).
List<Object[]> listaObjects = theRepository.getEntityUsingDate(dateIni, dateEnd);
Question:
I want to understand Why using the same fecha (java.util.Date) the method getEntityUsingString works, but using the method getEntityUsingDate fails (
When I set the range using Date it does not bring me results, whereas when I set the range with String it does.).
In my opinion, it should yield the same result that complies with the range of dates.
What is the problem?
You did not write what error it was, so it's only my guess that the most likely error in this case is:
ORA-01861: literal does not match format string.
If this is the case, then the reason is that you are passing to the query two values of date type:
Date dateIni = calendar.getTime();
.....
Date dateEnd = calendar.getTime();
.....
theRepository.getEntityUsingDate(dateIni, dateEnd);
these values are bind to this parameters :stringIni and :stringEnd
BETWEEN TO_DATE(:stringIni,'dd/MM/yyyy hh24:mi') AND TO_DATE(:stringEnd,'dd/MM/yyyy hh24:mi')
Since TO_DATE( char, [format] ) functions expects CHAR (string) as a first parameter, but gets a date, then according to rules explained in this documentation see section: implicit conversion
The following rules govern implicit data type conversions: .... ....
When you use a SQL function or operator with an argument of a data
type other than the one it accepts, Oracle converts the argument to
the accepted data type.
it does an implicit conversion from date to string using TO_CHAR function.
This function uses the default date language from a session to format strings, so depending of this settings the date may be converted to something like 12/15/54, 19-06-11 12:23 PM, JUN 23, 2019 13:20 AM +01 etc.
This string 12/15/54 is then passed to TO_DATE(:stringIni,'dd/MM/yyyy hh24:mi'), and because this sting doesnt match format string, the error is thrown: ORA-01861: literal does not match format string

Postgres Timestamp column with Java util.Date

I have a (start_time) column which is of type timestamp with time zone. and I have a JPA mapping entity which reads as below,
#Column(name = "start_time")
#Temporal(TemporalType.TIMESTAMP)
private Date startTime;// (util.date)
My table has value "2017-08-09 09:57:00+05:30". When I use JPA to map the values, I get the value as "2017-08-09 09:57:00.0"
when I try to debug, I can see CDATE inside the date attribute which shows me the correct value with timezone. How to map this correctly?
Try to change #Column(name = "start_time") on #Column(name = "start_time", columnDefinition = "TIMESTAMP WITH TIME ZONE")

Queries in EJB QL Collection Member Comparison

I need to write the following sql query, in EJBQL.
SELECT * FROM teacher t left join student_class sc on t.id_teacher = p.id_student_class where t.login = 01325 and sc.id_student_class = 3;
In the class bean Teacher, there is the following relantionship:
#Column(name = "login")
private String mLogin;
#OneToMany(mappedBy = "mTeacher", fetch = FetchType.LAZY)
private List<StudentClass> mStudentClassList ;
I know how start it:
SELECT mTeacher FROM Teacher mTeacher INNER JOIN mTeacher.mStudentClassList mStudentClassList WHERE mTeacher.mLogin = 01325 AND mStudentClassList
... ???
Can anyone help me?

Resources