Insert Instant datetime into MySql database with millisecond precision in java - java

I am using mysql 5.7.x version. Also i am using java 8. I am trying to insert java.time.instant current datetime in millisecond precision into my mysql database from java code. For that I am using preparedstatement.
The table in my database is:
CREATE TABLE `test_table` (
`id` INT NOT NULL AUTO_INCREMENT,
`timestamp` TIMESTAMP(3) NOT NULL,
PRIMARY KEY (`id`));
My java code to insert is:
Instant instant = Instant.now().truncatedTo(ChronoUnit.MILLIS);
try (Connection conn = DbConnection.getCon();
PreparedStatement ps = conn.prepareStatement("INSERT INTO test_table (timestamp) VALUES (?)");) {
ps.setTimestamp(1, Timestamp.from(instant));
ps.executeUpdate();
LOG.info("Instant: {} and long: {}", instant, instant.toEpochMilli());
} catch (SQLException ex) {
LOG.error(ex.getMessage());
}
From my log, I can see instant with milliesecond as: 2019-07-30T10:52:34.865Z.
But in my mysql database it becomes: 2019-07-30 10:52:34.000Z
I have searched so many questions and answers in stack but none seems to work for me.
Update 1:
I tried using setObject as:
ps.setObject(1, Timestamp.from(instant));
But still same result. Cannot retrieve the milliseconds in database.

MySQL has FROM_UNIXTIME() function that can take long values inside and returns a representation of the unix_timestamp in 'YYYY-MM-DD hh:mm:ss' or 'YYYYMMDDhhmmss.uuuuuu' format.
Reference from their manual here:
FROM_UNIXTIME()
Since I have milliseconds since epoch, thus I have to use
FROM_UNIXTIME(instant.toEpochMilli() * 0.001)
in my insert statement.
Yes nothing needs to be changed in database. The only things that are changed are in java code which are setObject() function used for preparedStatement, passing instant.toEpochMilli() as the argument there and finally use of FROM_UNIXTIME() function inside insert statement.
My final java code looks something like this:
Instant instant = Instant.now().truncatedTo(ChronoUnit.MILLIS);
try (Connection conn = DbConnection.getCon();
PreparedStatement ps = conn.prepareStatement("INSERT INTO test_table (timestamp) VALUES (FROM_UNIXTIME(?*0.001))");) {
ps.setObject(1, instant.toEpochMilli());
ps.executeUpdate();
LOG.info("Instant: {} and long: {}", instant, instant.toEpochMilli());
} catch (SQLException ex) {
LOG.error(ex.getMessage());
}

Related

How can I use strftime function with question mark in Java

I am planning to add 'Date' objects into the SQLite database. However, I am getting an error about the insertion being null.
The error is this
org.sqlite.SQLiteException: [SQLITE_CONSTRAINT_NOTNULL] A NOT NULL constraint failed (NOT NULL constraint failed: dates.Tarih)
at org.sqlite.core.DB.newSQLException(DB.java:909)
at org.sqlite.core.DB.newSQLException(DB.java:921)
at org.sqlite.core.DB.execute(DB.java:825)
at org.sqlite.jdbc3.JDBC3PreparedStatement.execute(JDBC3PreparedStatement.java:53)
This is my code. I suspect from the question marks. Because when I remove them and place them with 'now'. It actually works. But, the following code throws the above error.
Insert method
public static void insert(Date date, Date date2) {
try{
System.out.println(" date:"+date.toString());
String query = "insert into dates(Tarih,Tarih2) values(strftime('%d-%m-%Y',?), strftime('%d-%m-%Y',?))";
pst=conn.prepareStatement(query);
pst.setObject(1,date);
pst.setObject(2,date2);
pst.execute();
}catch (SQLException e){
e.printStackTrace();
}
}
Probably you have defined the column Tarih as NOT NULL and your code is trying to insert a null value in the table.
The reason that you get null from strftime() is because you don't pass a valid date for SQLite.
For SQLite valid dates/datetimes are either strings in the format yyyy-MM-dd hh:mm:ss, or integer unix epoch times or floating point numbers representing julian days.
What you pass are Date objects and this is your mistake.
One way to solve the problem is to extract from each of the Date objects an integer representing unix epoch time and pass that to strftime():
public static void insert(Date date, Date date2) {
try{
long d = date.toInstant().toEpochMilli() / 1000;
long d2 = date2.toInstant().toEpochMilli() / 1000;
String query = "insert into dates(Tarih,Tarih2) values(strftime('%d-%m-%Y', ?, 'unixepoch'), strftime('%d-%m-%Y', ?, 'unixepoch'))";
pst=conn.prepareStatement(query);
pst.setLong(1, d);
pst.setLong(2, d2);
pst.execute();
} catch (SQLException e){
e.printStackTrace();
}
}

java.sql.Timestamp to Date Conversion in Oracle SQL

I have run into this weird Timestamp to Date Conversion issue in Oracle SQL.
Here is the SQL statement:
String INSERT_SQL = String.format("INSERT INTO AUDIT_TASK (%s, %s, %s, %s) VALUES (AUDIT_TASK_SEQ.nextval,?,?,?)",ID,CLASS_NAME,TASK_STEP_TIMESTAMP,OPERATOR);
java.util.Calendar utcCalendarInstance = Calendar.getInstance(TimeZone .getTimeZone("UTC"));
java.util.Calendar cal = Calendar.getInstance();
final PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
stmt.setString(1, audit.getClassName().getValue());
// Save the timestamp in UTC
stmt.setTimestamp(2,new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
When I execute this statement, while most of the times the creation_date and task_step_timestamp dates are same, but sometimes I get the task_step_timestamp generated with some bogus dates- like '25-APR-0000' or '00-Jan-0001' etc.
ID | Creation_date | Task_step_timestamp
1 |27-APR-2018 17:58:53| 25-APR-0000 09:00:45
2 |27-APR-2018 18:06:25| 00-Jan-0001 09:18:25
The data type of task_step_timestamp column in Oracle DB is 'DATE'.
Can some one suggest the cause of this inconsistent conversion of timestamp to date?
I don't understand why you are using String#format here. Just use a regular insert which mentions explicit columns:
String INSERT_SQL = "INSERT INTO AUDIT_TASK (ID, ERROR_MESSAGE, TASK_STEP_TIMESTAMP, OPERATOR) ";
INSERT_SQL += "VALUES (AUDIT_TASK_SEQ.nextval, ?, ?, ?)";
PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
Then bind your values:
stmt.setString(1, audit.getErrorMessage() != null ? audit.getErrorMessage().getValue() : null);
stmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
stmt.setString(3, audit.getClassName().getValue());
Note carefully that the placeholders, in order from left to right, are for the error message, task step timestamp, and operator. Your original code appears to be binding the parameters out of order. By using an insert statement which explicitly mentions the columns, you may avoid this problem.
Edit:
It also doesn't make sense to me why you are worrying about time zones for your timestamp. Just get the numbers of milliseconds since the epoch, and then let the database store that as UTC:
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
stmt.setTimestamp(2, timestamp);

Retrieving Timestamp data from DB using Mysql

I have a Java MVC model.Which has timestamp as one of the DB value which is already inserted into DB.I have declared the data type as Timestamp in DB,Now the problem is If i try to retrieve it is showing null values & can not be represented as java.sql.Timestamp
Statement :
pstmt = con.prepareStatement("SELECT timestamp, FROM nid where id=?");
pstmt.setDouble(1, nidev);
rs = pstmt.executeQuery();
if(rs.next())
{
timeBean.setHbtimestamp(rs.getTimestamp("timestamp"));
}
Bean Class:
private Timestamp hbtimestamp;
public Timestamp getHbtimestamp() {
return hbtimestamp;
}
public void setHbtimestamp(Timestamp hbtimestamp) {
this.hbtimestamp = hbtimestamp;
}
MyDB value is successfully inserted :2015-05-14 15:45:57
output: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
Set in your MySQL
zeroDateTimeBehavior=convertToNull
Then empty time stamp values will be interpreted as NULLs
Well explained here

java sql - insert timestamp into sql database

I'm trying to insert a timestamp into a database, but my code throws an exception, which tells me it's something with my sql statement.
The exception message shown is:
"Fout in Rit_ToevoegenController.okKnop(): SQLException in RitDB.voegRitToe() - statement"
okKnop is a different method that calls voegRitToe().
The type of the column called 'starttijd' is TIMESTAMP, and the DB Data type is DateTime.
i'm fairly certain that it's the timestamp that causes problems, because the other 2 are just a String and an int.
Any help with making it work would be greatly appreciated. I need to insert both the time and date into the database for comparing later.
public void voegRitToe(Rit r) throws DBException{
Timestamp starttijd = new Timestamp(System.currentTimeMillis());
//Date date = new Date(starttijd.getTime());
try(Connection conn = ConnectionManager.getConnection();){
try(PreparedStatement stmt = conn.prepareStatement("insert into rit(starttijd, lid_rijksregisternummer, fiets_registratienummer) values(?,?,?)");){
stmt.setTimestamp(1, starttijd);
stmt.setString(2, r.getLid().getRegisterNr());
stmt.setInt(3, r.getFiets().getRegisNr());
stmt.execute();
}
catch(SQLException sqlEx){
throw new DBException("SQLException in RitDB.voegRitToe() - statement");
}
}
catch(SQLException sqlEx){
throw new DBException("SQLException in RitDB.voegRitToe() - verbinding");
}
}
TIMESTAMP and DATETIME serve different purposes; TIMESTAMP is for automatic time stamping.
java.util.Date starttijd = new java.util.Date(System.currentTimeMillis());
java.util.Date starttijd = new java.util.Date(); // Or this
I guess you came at Timestamp, as java.sql.Date wraps java.util.Date by setting the time part to zero!
If the database server's time is correct, one could also do:
... VALUES(NOW(), ?, ?)
By the way, java 8 introduces new date/time classes and "improve" upon the JDBC usage, if you have a java 8 compliant driver.

How do I properly get a SQL Datetime back into my Java application?

I'm having trouble with retrieving queries from my SQL database. I can get the blasted things added to the database, but I'm having an inordinate amount of difficulties performing the reverse. Three things, in order:
The SQL Table itself:
CREATE TABLE patientInstructions (
id INT UNSIGNED AUTO_INCREMENT,
lastUpdated datetime NOT NULL,
PatientID BIGINT UNSIGNED NOT NULL,
HCPID BIGINT UNSIGNED NOT NULL,
OVid BIGINT UNSIGNED NOT NULL,
urlLink VARCHAR(250) NOT NULL,
linkInstructions VARCHAR(500) NOT NULL,
linkName VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
) AUTO_INCREMENT=1 ENGINE=MyISAM;
The method call that is failing (I'm getting -1L instead of the actual data value stored in the database, which is why I know there's a problem in the first place):
public String getLastUpdated(long ovID) throws DBException {
try {
return psiDAO.getLastUpdated(ovID);
} catch (myOwnException e) {
e.printStackTrace();
return "-1L";
}
}
And finally, the method call which is failing:
public String getLastUpdated(long ovId) throws DBException {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = factory.getConnection();
ps = conn.prepareStatement("SELECT * FROM patientInstructions"
+ " WHERE ovId=?");
ps.setLong(1, ovId);
ResultSet rs = ps.executeQuery();
java.util.Date updated = new java.util.Date();
updated = rs.getTime("lastUpdated");
return updated.toString();
} catch (SQLException e) {
e.printStackTrace();
throw new DBException(e);
} finally {
DBUtil.closeConnection(conn, ps);
}
}
What Java object matches a SQL Datetime? I've tried rs.getTimestamp, rs.getDate, etc. but haven't had any more success (though I'm not ruling out that I botched those up either). Am I making a mistake transferring the data from the resultset back to Java object?
You must call ResultSet.next() on a ResultSet before accessing each row, including the first. You're not doing that here; the exception message should actually be telling you this.
There are three classes: java.sql.Date, java.sql.Time, and java.sql.Timestamp. I'm not sure which one most closely corresponds to a DATETIME in SQL. All three derive from java.util.Date, which is why you are able to assign the result of calling rs.getTime to one.
I don't have a setup here that would allow me to test it, but I would try using one of the types from java.sql.* and see what results that gives you.
Whoops! I posted my answer before Ernest's and I didn't even notice the missing rs.next(). That is definitely your problem, and I bet java.util.Date will work just fine for you, with that change.
Since your datatype is datetime, you will need to use getTimestamp()... see here for more datatype mapping information.
So, your code should look something like this:-
...
ResultSet rs = ps.executeQuery();
String updated = "";
if (rs.next()) {
updated = rs.getTimestamp("lastUpdated").toString();
}
rs.close();
ps.close();
return updated;
Please paste the exception here. You need to call ResultSet's next method before retrieving the values from the result set. Also, try java.sql.Timestamp lastUpdatedTimestamp = getTimestamp("lastUpdated")
If needed , you can convert timestamp to String later.

Categories

Resources