Spring data with custom query - like, between, like and order by - sql

how I can pass this string "sql" for a Spring Data #Query?
My Class Resources:
public void findMessage(String startDate, String endDate, String id, String values, String fieldName, String sort){
String sql = "SELECT e FROM message e WHERE (e.create_at BETWEEN '"+
startDate+ "' AND "+"'"+ endDate +"') AND (e.id = '"+id+"')
AND (e.category LIKE '%"+values+"%') ORDER BY
e."+fieldName+" "+sortParam;
}
My Custom Repository:
public interface CustomMessageRepository extends PagingAndSortingRepository<Message,Long>{
#Query(value = **MyStringSql**)
public Page<Message> find(Pageable page);
}
I'm using JHipster + Spring Data. Using the examples I found, just can not run queries are passed parameter as fieldName and sort.
What is the solution?
Thank you.

Related

SQLNative query returning empty results

I'm trying to execute a query which needs 4 tables :
#Query(value="SELECT e.* FROM erreur e, synop sy, synop_decode sd, station st WHERE e.id_synop = sd.id_synop_decode "
+ "and sd.id_synop_decode = sy.id_synop" + " and DATE(sy.date)= :date and "
+ "sy.id_station = st.id_station and st.id_station= :stationId", nativeQuery=true)
public List<Erreur> recherche(#Param("date") Date date, #Param("stationId") Long stationId);
This query works fine et native sql, i pass an existing stationId and a date like the following :
SELECT e.* FROM erreur e, synop sy, synop_decode sd, station st WHERE e.id_synop = sd.id_synop_decode and sd.id_synop_decode = sy.id_synop
and DATE(sy.date)= '2019-05-27' and sy.id_station = st.id_station and st.id_station= 60355;
This query works fine in Mysql Workbench.
Here's the actual controller i'm using for testing purpose :
#GetMapping("/station/{stationId}/erreurs/today")
public List<Erreur> getTodayErreurByStationId(#PathVariable Long stationId)
{
List<Erreur> erreurs = new ArrayList<Erreur>();
Optional<Station> stationOptional = stationRepository.findById(stationId);
if(stationOptional.isPresent())
{
return erreurRepository.recherche(new Date(), stationId);
}
return null;
}
The expected results are the actual "Ererur" objects in my array list, but RestClient just returns an empty array [], while the query works just fine in mysql like i described it above.
So my question is : How can i write this query into Hql language so that i can return the right entities. Or how can i map my sql results to my target custom calss "Erreur"?
#Entity
#Getter #Setter #NoArgsConstructor
#Table(name="erreur")
public class Erreur {
public Erreur(int section, int groupe, String info) {
this.section = section;
this.groupe = groupe;
this.info = info;
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_erreur")
private Long id;
#ManyToOne(cascade= {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},
fetch=FetchType.LAZY)
#JsonIgnore
#JoinColumn(name="id_synop")
private SynopDecode synopDecode;
#OneToOne
#JoinColumn(name="id_controle")
private Controle controle;
#ManyToOne(cascade= {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},
fetch=FetchType.LAZY)
#JsonIgnore
#JoinColumn(name="id_station")
private Station station;
#Column(name="section")
private int section;
#Column(name="groupe")
private int groupe;
#Column(name="info")
private String info;
}
If you want to use jpa convention directly then you will have to make associations between different entities i.e. how two entities are linked. When we define these associations then spring jpa knows how to convert method name or custom queries into SQL.
Your code will need to be something like
public class Erreur {
...
#ManyToOne
#JoinColumns//define how Erreur and SynopeDecone are linked
private SynopDecode synopDecode;
...
public class SynopDecode {
...
#ManyToOne // or #OneToOne its not mentioned in question how these two are linked
#JoinColumns//define how SynopDecode and Synop are linked
private Synop synop;
...
Then you can write your query like
#Query("select e from Erreur e LEFT JOIN e.synopDecode sy LEFT JOIN sy.synop sy WHERE DATE(sy.date) = :date AND sy.id_station = :stationId")
List<Erreur> getByDateAndStationId(#Param("date") Date date, #Param("stationId") Long stationId)
You can't use method name based query because you want to use SQL function to match only "date" part of your date and not the whole timestamp.
You can use jpa methods by conventions.
Assuming SynopDecode has property like:
//SynopDecode class
#ManyToOne
private Synop synop;
//repository interface
List<Erreur> findByStationIdAndSynopDecodeSynopDate(Long stationId, Date date);
//or
//List<Erreur> findByStationIdAndSynopDecode_Synop_Date(Long stationId, Date date);
UPDATE
As Punit Tiwan (#punit-tiwan) note that, the above methods used for a specific datettime.
You can use methods below for just DATE.
//repository interface
List<Erreur> findByStationIdAndSynopDecodeSynopDateBetween(Long stationId, Date startOfDate, Date endOfDate);
//or
//List<Erreur> findByStationIdAndSynopDecode_Synop_DateBetween(Long stationId, Date startOfDate, Date endOfDate);
I figured a way to get the same results as my SQL Query using the #Query annotation and accessing object properties like this :
#Query("from Erreur e where e.synopDecode.synop.station.id = :stationId and "
+ "DATE(e.synopDecode.synop.date) = :date")
public List<Erreur> recherche(#Param("date") Date date, #Param("stationId") Long stationId);
I think it solves my problem, thanks for the help

Spring data repository query to retrieve values containing null

I have following User table and repository.
User:
id;name;job;age
1;steve;nurse;33
2;steve;programmer;null
3;steve;programmer;null
Repository method:
#Query("SELECT u FROM User u WHERE ("
+ "LOWER(u.name) = LOWER(:name) AND "
+ "LOWER(u.beruf) = LOWER(:job) AND "
+ "LOWER(u.alter) = LOWER(:age))")
public List<User> findUsers(#Param("name") String name,
#Param("job") String job,
#Param("age") String age);
If I call the repository method with following parameters
String name = "steve";
String job = "programmer";
List<User> result = repository.findUsers(name, job, null); // empy list ..why ?
I get an empty list as result, although I expect to get the entities with id=2 and id=3 as result.
What am I doing wrong ? How should I change the query to get the two entities as result.
Thanks
According to the documentation this behaviour is normal there is no way to ignore null fields. using #Query method.
instead you can use the query method specifications.
more information [here][jpa documentaiton]
if you want to keep your existing method you can also go like this:
#Query("SELECT u FROM User u WHERE ("
+ "LOWER(u.name) = LOWER(:name) AND "
+ "LOWER(u.beruf) = LOWER(:job) AND "
+ "( " +
" :age is null or LOWER(u.alter) = LOWER(:age) " +
")"
)
public List<User> findUsers(#Param("name") String name,
#Param("job") String job,
#Param("age") String age);

Spring jdbcTemplate query always returns null irrespective of data in database

I need to fetch a sum value from database based on date range. I tried using Spring jdbcTemplate in the following ways. But it doesn't return anything.
public void getTotal(String from, string toDate){
String totalSql="select sum(b.finalAmount) as total from example a, example b "+
"where a.created >= TO_TIMESTAMP(:fromDate, 'MM-DD-YYYY') AND a.created < TO_TIMESTAMP(:toDate, 'MM-DD-YYYY hh24:mi:ss') "+
"and a.tradein_id=b.tradein_id";
List<Integer> checkAmt = jdbcTemplate.query(sql, new RowMapper<Integer>() {
#Override
public Integer mapRow(ResultSet rs, int rowNum) throws SQLException
{
int check = rs.getInt("TOTAL");
return check;
}
}, fromDate,toDate);
int checkAmount = jdbcTemplate.queryForObject(
totalSql, new Object[]{fromDate, toDate},Integer.class);
}
When I hardcode the fromDate and toDate in query, it works fine. I assume there is something wrong with the select parameters I am sending in.
Both from date and todate are String values from front end of the format 08/09/2016.
The SQL is using named parameters but the code is sending a list of arguments. Either use a NamedParameterJdbcTemplate and change how you're passing in arguments, or use a JdbcTemplate and change the SQL to use the ? placeholder instead of named arguments.
If you use NamedParameterJdbcTemplate, you have to refer to the parameters by name in the SQL, and you have to provide names when passing in the arguments. Put them in a map, like this (from the spring-jdbc documentation):
public int countOfActorsByFirstName(String firstName) {
String sql = "select count(*) from T_ACTOR where first_name = :first_name";
SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
}
Alternatively you can provide the arguments like this:
Map args = new HashMap();
args.put("fromDate", fromDate);
args.put("toDate", toDate);
jdbcTemplate.queryForObject(sql, args, Integer.class);
If you don't want to use named parameters, change the SQL to look like
String totalSql= "select sum(b.finalAmount) as total from example a, example b "+
"where a.created >= TO_TIMESTAMP(?, 'MM-DD-YYYY') AND a.created < TO_TIMESTAMP(?, 'MM-DD-YYYY hh24:mi:ss') "+
"and a.tradein_id=b.tradein_id"
and leave the rest alone.

How to select rows from SQLite table which fall between today's date and 7 days time

public class DbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "assignment_info.db";
public static final String ASSIGNMENT_ID = "_id";
public static final String ASSIGNMENT_VALUE = "assignment_value";
public static final String ASSIGNMENT_RESULT = "assignment_result";
public static final String SUBJECT = "subject";
public static final String ASSIGNMENT_TITLE = "assignment_title";
public static final String DUE_DATE = "due_date";
public static final String NOTES_ASSIGNMENT = "notes";
public static final String TABLE_NAME_ASSIGNMENT = "assignment_information";
private static final String ADD_QUERY = "CREATE TABLE "+
TABLE_NAME_ASSIGNMENT+"("+
ASSIGNMENT_ID+" INTEGER PRIMARY KEY AUTOINCREMENT,"+
SUBJECT+" TEXT,"+
ASSIGNMENT_VALUE+" INTEGER,"+
ASSIGNMENT_RESULT+" DOUBLE,"+
ASSIGNMENT_TITLE+" TEXT,"+
DUE_DATE+" DATE,"+
NOTES_ASSIGNMENT+" TEXT);";
public DbHelper(Context context){
super(context,DATABASE_NAME,null,DATABASE_VERSION);
Log.e("Database Operations","Database opened/created from constructor.");
}
#Override
public void onCreate(SQLiteDatabase db) {
//IF DATABASE IS CREATED FOR FIRST TIME THIS METHOD WILL BE CALLED
db.execSQL(ADD_QUERY);
db.execSQL(ADD_NOTES_QUERY);
Log.e("Database Operations"," DbHelper - onCreate called ");
}
I have an SQLite table which contains dates stored as strings >>
"+ DUE_DATE+" STRING," .
I want to select all rows which fall between todays date and 7 days from now.
This is what I have so far, and it will not return any results,
String sql = "SELECT * FROM " + TABLE_NAME_ASSIGNMENT + " WHERE "+ DUE_DATE + " >= date('now') AND date('now','+7 days')";
Can anyone please help??
Thanks
CREATE TABLE TABLE_NAME_ASSIGNMENT
(ASSIGNMENT_ID INT, SUBJECT TEXT, ASSIGNMENT_TITLE TEXT, DUE_DATE DATE)
;
INSERT INTO TABLE_NAME_ASSIGNMENT
(ASSIGNMENT_ID, SUBJECT, ASSIGNMENT_TITLE, DUE_DATE)
VALUES
(1, 'MATHS', 'Prime Numbers', '2015-08-22'),
(2, 'SCIENCE', 'Periodic Table', '2015-08-30'),
(3, 'MATHS', 'Odd Numbers', '2015-09-02')
;
SELECT
*
FROM
TABLE_NAME_ASSIGNMENT
WHERE Due_Date BETWEEN date('now') AND date('now','+7 days')
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''+7 days')' at line 10
Have you tried using BETWEEN?
String sql = "SELECT * FROM " + TABLE_NAME_ASSIGNMENT + " WHERE "+ DUE_DATE + " BETWEEN date('now') AND date('now','+7 days')"
Also make sure that DUE_DATE is type DATE of the form YYYY-MM-DD
As in your table you have stored date as string type so you can not retrieve data in traditional way unless you convert your date string in actual date format while executing query.
Please try once again using the following query.
SELECT
*
FROM
Mytable
WHERE
DATE(substr(fecha ,1,4) ||substr(fecha ,6,2)||substr(fecha ,9,2))
BETWEEN
DATE(20140105)
AND
DATE(20140105);

How to handle null pointer exceptions in elasticsearch

I'm using elasticsearch and i was trying to handle the case when the database is empty
#SuppressWarnings("unchecked")
public <M extends Model> SearchResults<M> findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
BoolQueryBuilder qb = buildQueryBuilder(search, searchFields, where);
Query<M> query = (Query<M>) ElasticSearch.query(qb, entityClass);
// FIXME Currently we ignore the orderBy and order fields
query.from((page - 1) * getPageSize()).size(getPageSize());
query.hydrate(true);
return query.fetch();
}
the error at return query.fetch();
i'm trying to implement a try and catch statement but it's not working, any one can help with this please?