I would like to check the DB if a record already exists for a give run date and name using Spring JPA query using two params:
#Query("SELECT CASE WHEN COUNT(r)> 0 THEN true ELSE false END FROM REQUEST r WHERE r.NAME = :reqName AND r.RUN_DATE = :runDate")
boolean existsRequest(#Param("reqName") String reqName,
#Param("runDate") String runDate);
The type of RUN_DATE in Database H2, Sql Server is a DATE field. Yet I am providing String as param for the date in format YYYY-MM-DD.
The above doesn't work for me and I was wondering how to write it correctly using both JPQL and nativeQuery ?
For this specific case, I think the most elegant way is to use query method:
boolean existsByNameAndRunDate(String name, String runDate);
Related
I use spring boot, and I want to add 1 year to a specific column in mysql database
String queryRecherche = "UPDATE myTable t SET t.dateDebut = DATE_ADD(t.dateDebut, INTERVAL 1 YEAR) WHERE.id = 3 ";
Query query = em.createQuery(queryRecherche);;
query.executeUpdate();
But I get the folowing error :
org.hibernate.query.sqm.ParsingException: line 1:66 no viable alternative at input 'DATE_ADD(t.dateDebut,INTERVAL1'
Have you please any suggestions to do this.
You're using Hibernate 6 (I can tell by the error message), so the correct HQL syntax to use is:
UPDATE MyEntity t SET t.dateDebut = t.dateDebut + 1 year WHERE t.id = 3
You had three errors in your query:
You referred to the name of a table instead of the name of an entity class in the UPDATE clause.
You used the unportable MySQL DATE_ADD function instead of the portable HQL date/time arithmetic described here.
The syntax of your WHERE clause was garbled.
Perhaps you meant for this to be a native SQL query, in which case you called the wrong method of Session. But there's no need to use native SQL for the above query. As you can see, HQL is perfectly capable of expressing that query.
You can use SQL directly, via createNativeQuery, or register a new function as shown in this example to call it from HQL
I have problem with HQL where I am setting the query parameters. One of them is Date. When I debug the code there is Date with time entering the method. I set the parameter using setParameter(timestamp, new Timestamp(date.getTime())) or query.setTimestamp...etc etc I used many combinations...
When I use p6spy to examine the SQL comming from app to the DB there is only '29-Jan-21' or other date without time.
I am using hibernate 5.1.0 final and postgre DB. I'll be glad for any help.
Example:
Query query = getSessionFactory().getCurrentSession().createQuery("SELECT user FROM UserEntity cr WHERE user.userStatus.id = :statusId AND :timestamp >= user.valid_to");
This is how I tried to set the timestamp parameter:
query.setParameter("timestamp", new Timestamp(date.getTime()));
query.setParameter("timestamp", date, TimestampType.INSTANCE);
query.setTimestamp("timestamp", date);
query.setTimestamp("timestamp", new Timestamp(date.getTime()));
Problem is that the generated SQL replace timestamp by '29-Jan-21' or other date I choose but without time. The date parameter comes to the method from UI and it contains full date with time.
I'm using Java 8 with Spring's JdbcTemplate and Oracle 12.1,
I want to update record and get the exact time record was updated
jdbcTemplate.update(UPDATE_SQL, null);
Currently it returns (int) the number of rows affected, but I want the exact updated date
Must I send a new request to get current time which may be inaccurate?
More exact will be to save in column updated date, but then to execute another SQL
Is there another option to get updated date in one query?
Obviously, I don't want to use get date from code also (as new Date()) also because server time is/can be different than DB Time
You decided to use JDBCTemplate most probably to simplify the code in comparison to plain JDBC.
This particular problem IMHO makes the plain JDBC solution as proposed in other answer much simpler, so I'd definitively recommend to get the database connection from JDBCTemplate and make the insert in a JDBC way.
The simplest solution using JDBCTemplate that comes to my mind is to wrap the insert in a PROCEDURE and return the timestamp as an OUT parameter.
Simple example (Adjust the time logik as required)
create procedure insert_with_return_time (p_str VARCHAR2, p_time OUT DATE) as
BEGIN
insert into identity_pk(pad) values(p_str);
p_time := sysdate;
END;
/
The call is done using SimpleJdbcCall
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("insert_with_return_time");
SqlParameterSource params = new MapSqlParameterSource().addValue("p_str", str);
Map<String, Object> out = jdbcCall.execute(params);
The Map contains the returned value e.g. [P_TIME:2019-10-19 11:58:10.0]
But I can only repeat, in this particular use case is IMHO JDBC a rescue from JDBCTemplate;)
You're right that passing new Date() would store the server time rather than the DB time.
To store the DB time you can set your timestamp to the DB system timestamp systimestamp then you could run a query to retrieve that row and its updated timestamp.
If you want to update the row and get the updated timestamp in a single execution then you could do the following using RETURNING INTO where TimestampUpdated is your column name:
Connection con = ...;
String sql = "UPDATE TableName SET <updates> , TimestampUpdated = systimestamp RETURNING TimestampUpdated INTO ?";
CallableStatement statement = con.prepareCall(sql);
statement.registerOutParameter(1, Types.TIMESTAMP);
int updateCount = statement.executeUpdate();
Timestamp timestampUpdated = statement.getInt(1);
System.out.println("Timestamp Updated = " + timestampUpdated);
Here is a related link doing this with JdbcTemplate
When I use ignate's cast function, when the source data cannot be converted to target type, then ignite will throw this exception:
javax.cache.CacheException: Failed to run map query remotely.Failed to execute map query on the node: 3ed8c3f3-31d3-4e18-a41c-83e2b6d4bf4a, class org.apache.ignite.IgniteCheckedException:Failed to execute SQL query. Cannot parse "DATE" constant "xxxx";
But I need it to use null instead when it cannot be converted, just like the Postgresql database.
What should I do?
Ignite version:2.6,JDBC version:2.5
SELECT CAST(city AS DATE) AS `a1` FROM orders GROUP BY CAST(city AS DATE);
Expected:
a1
Null
Actual:
java.sql.SQLException: javax.cache.CacheException: Failed to run map query remotely.Failed to execute map query on the node: 3ed8c3f3-31d3-4e18-a41c-83e2b6d4bf4a, class org.apache.ignite.IgniteCheckedException:Failed to execute SQL query. Cannot parse "DATE" constant "xxxx"; SQL statement:
SELECT
CAST(__Z0.city AS DATE) __C0_0
FROM PUBLIC.ORDERS2 __Z0
GROUP BY CAST(__Z0.city AS DATE) LIMIT 3 [22007-195]
at org.apache.ignite.internal.jdbc.thin.JdbcThinConnection.sendRequest(JdbcThinConnection.java:751)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute0(JdbcThinStatement.java:210)
at org.apache.ignite.internal.jdbc.thin.JdbcThinPreparedStatement.executeWithArguments(JdbcThinPreparedStatement.java:252)
at org.apache.ignite.internal.jdbc.thin.JdbcThinPreparedStatement.executeQuery(JdbcThinPreparedStatement.java:78)
at com.uniplore.calculation.connectors.IgniteConnector.execute(IgniteConnector.java:58)
at tests.AbstractFunctionTransTest.getResult(AbstractFunctionTransTest.java:65)
at tests.IgniteFunctionTransTest.Date(IgniteFunctionTransTest.java:840)
Is that how PostgreSQL's CAST work? This post kind of suggests otherwise.
In any case, you can't change this behavior in Ignite. If you use the same value xxxx as a placeholder date, you can use CASE as a workaround:
SELECT CASE WHEN city = 'xxxx' THEN NULL ELSE CAST(city AS DATE) END AS a1
FROM orders GROUP BY a1
Ok,I know,CAST is a standard function that should return exceptions。
Mysql has a function called DATE that can return NULL values when the conversion fails,except ignite has no corresponding function.
The best way is to return the error to the user, or let the user use the PARSEDATETIME function instead.
I want to retrieve one of my column date in "mm/dd/yyyy" format. This column is currently returning date and time both but i want only date in "mm/dd/yyy" format.
Below is my postgresql query that i want to convert to criteria api
select DISTINCT c.name as Facility,
to_char(begin_exam,'mm/dd/yyyy') as begin_exam
from a inner join b on a.rad_exam_id = b.id
inner join c on c.id = b.site_id
group by c.name,to_char(begin_exam,'mm/dd/yyyy')
order by c.name,to_char(begin_exam,'mm/dd/yyyy')
I searched on the internet a lot but did't find any solution that will help me. please help me in writing criteria api query for this.
Criteria API defines function expression to execute native SQL functions in the CriteriaBuilder interface as follows:
<T> Expression<T> function(String name, Class<T> type, Expression<?>... args);
where name is the name of the SQL function, type is the expected return type and args is a variable list of arguments (if any).
Here is an example how to use it in a Criteria query:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(String.class);
Root<RadExamTimes> root = cq.from(RadExamTimes.class);
cq.select( cb.function("to_char", String.class, root.get("begin_exam"), cb.literal("MM/DD/YYYY")));
TypedQuery<String> query = entityManager.createQuery(cq);
List<String> result = query.getResultList();
where
RadExamTimes: a hypothetical root entity
MM/DD/YYYY: a database-specific format (in this example
Postgresql date format; for Oracle use Ora format, etc)
to_char: Postgresql function to convert date value to string
begin_exam: the date field to be formatted
The format string cannot be passed as is so that the literal() method is used to wrap it.
Note: The above example is tested on MySQL database with MySQL function and corresponding date format; but the example changed to match Postgresql syntax.
SELECT '2001-02-16 20:38:40'::date;
date
----------------
2001-02-16
(1 row)
Or you can use #TemporalType on JPA entity field.
If you want to display the column date in "mm/dd/yyyy" format for the sake of displaying it in the front end. Following might work on this case.
public class SomeDTO {
#JsonFormat(pattern="mm/dd/yyyy")
private Date someDate;
}