I have been given some code to work on. I need to modify the existing code to return an extra column. Using the tool, SQLDeveloper, I can see an example record (notice Date AND Time information is present):
30-NOV-17 15:54:00
The code that I have been given to work on does the following:
// Create a Hibernate query (Oracle SQL query)
Query query = session.createSQLQuery(<NATIVE_SQL_QUERY_HERE>);
List<Object[]> rawDataRows = query.list();
if (rawDataRows != null) {
for(Object[] rawDataRow : rawDataRows) {
// I am trying to get the Date AND Time here
Timestamp ts = (Timestamp) rawDataRow[7];
}
}
The problem is that I get an error when I try this approach (Cannot cast java.sql.Date to Timestamp).
When I access the data without the cast (just get the data in a Date object), I DO NOT get the Time information. And I need to have BOTH.
So far, nothing I have tried has worked - other posts have similar issues, but they are not quite the same.
Any advice/suggestions much appreciated - THANKS!
You can use this code:
....
Calendar calendar = Calendar.getInstance();
calendar.setTime(rawDataRow[7]);
Timestamp ts = new Timestamp(calendar.getTimeInMillis());
...
Related
We recently updated a project from using Hibernate 4 to Hibernate 5.2, and with that came the need to update all of our Criteria to use JPA. For the most part things are in working order, but I have one query that is no longer behaving. One of the fields on the table we are querying is of type DATE in the database.
When I query directly on the table I get back the date- say it is "2017-04-20." However, when I run the same query on our development server, using JPA's createNativeQuery, I get back the date "2017-04-19"
I don't think this is an issue with the query as I run the exact same query both through a mysql terminal and through java and get different results. The query that I run is the one that is logged in my below example. I think it may be a timezone issue as I don't have this problem on my local environment, just on my dev server, but it also wasn't a problem until we updated to the new versions of Hibernate.
public List<ResponseDTO> getDashboardData(String date, Integer page, Integer pageSize, AbstractDashboard dashboard) {
List<ResponseDTO> processed = new ArrayList<ResponseDTO>();
String query = getDashboardQuery(date, dashboard);
logger.info("Dashboard Query: " + query);
List<Object[]> raw = createNativeQuery(query).getResultList();
return raw.stream().map(r->new ResponseDTO(r)).collect(Collectors.toList());
}
And the constructor of my DTO object:
public ResponseDTO(Object[] r) {
this.date = ((Date) r[0]).toLocalDate();
System.out.println(this.date.toString());//This date does not match what is in the db.
this.type = (String) r[1];
this.label = (String) r[2];
this.value = (Double) r[3];
}
Edit:
I think it's actually an issue with the java.sql.Date type, because I tried printing that out on my dev server and it also returns "2017-04-19" instead of the 20th. I don't get why this doesn't match the results when I run the query in a mysql console, it seems like they should be the same to me.
Try another JDBC driver
Ok, I got it working. For what it's worth, this seems like complete madness to me. The "Aha!" moment came while reading this answer to a different question.
Since it is the mysql driver that dictates how the date is parsed in the system. I rolled back my mysql driver as that was one of the packages that I updated. Suddenly everything behaved as expected.
When I query MongoRepository via Date field with Criteria in a Spring Boot application, the result is wrong. Here is my method:
Query query = new Query(new Criteria().andOperator(
Criteria.where("id").is(filter.getId()),
Criteria.where("datas.ts").lt(filter.getEndTime()).gte(filter.getStartTime())
));
List<PhaseData> phaseDatas = mongoOperations.find(query, PhaseData.class);
List<Data> result = new ArrayList<Data>();
for(Data pData : phaseDatas) {
result.addAll(pData.getDatas());
}
return result;
When I query with
{
"id" : "1234",
"startTime" : "2016-08-04 12:00",
"endTime" : "2016-08-04 15:00"
}
it gives me records with hour 16:54 & 21:12 too. How can I solve this issue?
Not sure if this addresses your question directly.
The DB won't return wrong result to the query. So I think it could be one of the following things:
It could be that the when you view the documents in mongodb, it displays date in iso format. So view the documents in the same format as you are creating dates for your query.
It could be timezone issue.
Mongodb dates can be considered as ISODate (MongoDB Date)
When you query, you create date objects in your timezone. So as a first debugging measure, I would see if both my DB and query timezones are the same.
Also, probably it would help if you query by creating date objects in ISODate by using SimpleDateFormat(SDF is not thread safe).
I have found that it could be confusing because the dates that you send are in a different format and the documents that you visually see in mongodb tool are displaying dates in iso format. I think that it could be the issue. The results are good, but probably you are viewing the two things differently and it causes the confusion.
Before I start, I have already searched around for an answer to this issue and the best answer I could come up with is this question
I have one difference though. I have a table that maintains a history of many documents. Therefore I need to query on an ID as well as the date range. Here is what my query currently looks like in Java
BasicDBObject searchQuery = new BasicDBObject();
searchQuery.put("id", id);
searchQuery.put("dateModified", BasicDBObjectBuilder.start("$gte", fromDate).add("$lte", toDate).get());
DBCursor cursor = table.find(searchQuery);
This returns no results. The MongoQuery that is generated by this block of code looks like this:
db.history.find({ "id" : 12345 , "dateModified" : { "$gte" : { "$date" : "2015-01-19T00:00:00.000Z"} , "$lte" : { "$date" : "2015-01-25T00:00:00.000Z"}}});
When I manually type this into MongoDB command line, this also returns no results. I currently have one record in the database for testing purposes that looks like this:
{
"id" : NumberLong(12345),
"dateModified" : ISODate("2015-01-21T19:42:28.044Z")
}
This object should clearly match the query, yet nothing is returning, any ideas?
EDIT: So it turns out that the string generated by the query object doesn't match the ISODate object in the database. I'd like to clarify that fromDate and toDate are both java.util.Date objects. I'm still not sure how to solve this though.
I figured out the issue. I don't understand the cause, but the issue is with the BasicDBObjectBuilder not using the Date object correctly. I switched to QueryBuilder and built the exact same query and it returned results.
fromDate must be of the type Date not the String representation. An ISODate in the MongoDB storage Engine is not equal to the String representation of the same date and so they do not match.
I got a little problem and I didn't find a suitable solution on the net because my question is a bit tricky for search engine.
There's a lot of topics about hibernate saving milliseconds. But my problem is something else.
In fact, I got a database, which save my date like this :
2014-03-20 10:58:09
I used Hibernate to get back my date, and display it on a web page. But Hibernate retrieve more than that : it also retrieve a 0 milliseconds, like this :
2014-03-20 10:58:09.0
Many people seems to have problem with this, but in my case, I DON'T WANT this information, I want Hibernate to retrieve the date without this .0 !
Thanks for your help !
EDIT AND SOLUTION :
Ok so I made it by using a little hack.
In my specific object using by Hibernate, I had this method :
public Date getModificationDate() {
return modificationDate;
}
I just simply create an other method :
private static final SimpleDateFormat FMT = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
public String getModificationDateLabel() {
if (modificationDate != null) {
return FMT.format(modificationDate);
}
return null;
}
So, when I display in my webpage (I use Velocity Template), I just run through my list of object an display the label :
#foreach( $object in $objects)
$!{object.modificationDateLabel}
#end
The SimpleDateFormat allow me to remove the .0, and by creating a new method, I don't disturb the behavior of getting a Date with Hibernate.
Thanks for your time !
I don't see a problem with the date returned as "2014-03-20 10:58:09.0" is equal to "2014-03-20 10:58:09". Can you provide specific scenario where this can result in issue?
Or use SimpleDateFormat("yyyy-MM-dd HH:mm:ss") then parse your date in this format before using the date.
I have an action in struts2 that will query the database for an object and then copy it with a few changes. Then, it needs to retrieve the new objectID from the copy and create a file called objectID.txt.
Here is relevant the code:
Action Class:
ObjectVO objectVOcopy = objectService.searchObjects(objectId);
//Set the ID to 0 so a new row is added, instead of the current one being updated
objectVOcopy.setObjectId(0);
Date today = new Date();
Timestamp currentTime = new Timestamp(today.getTime());
objectVOcopy.setTimeStamp(currentTime);
//Add copy to database
objectService.addObject(objectVOcopy);
//Get the copy object's ID from the database
int newObjectId = objectService.findObjectId(currentTime);
File inboxFile = new File(parentDirectory.getParent()+"\\folder1\\folder2\\"+newObjectId+".txt");
ObjectDAO
//Retrieve identifying ID of copy object from database
List<ObjectVO> object = getHibernateTemplate().find("from ObjectVO where timeStamp = ?", currentTime);
return object.get(0).getObjectId();
The problem is that more often than not, the ObjectDAO search method will not return anything. When debugging I've noticed that the Timestamp currentTime passed to it is usually about 1-2ms off the value in the database. I have worked around this bug changing the hibernate query to search for objects with a timestamp within 3ms of the one passed, but I'm not sure where this discrepancy is coming from. I'm not recalculating the currentTime; I'm using the same one to retrieve from the database as I am to write to the database. I'm also worried that when I deploy this to another server the discrepancy might be greater. Other than the objectID, this is the only unique identifier so I need to use it to get the copy object.
Does anyone know why this is occuring and is there a better work around than just searching through a range? I'm using Microsoft SQL Server 2008 R2 btw.
Thanks.
Precision in SQL Server's DATETIME data type does not precisely match what you can generate in other languages. SQL Server rounds to the nearest 0.003 - this is why you can say:
DECLARE #d DATETIME = '20120821 23:59:59.997';
SELECT #d;
Result:
2012-08-21 23:59:59.997
Then try:
DECLARE #d DATETIME = '20120821 23:59:59.999';
SELECT #d;
Result:
2012-08-22 00:00:00.000
Since you are using SQL Server 2008 R2, you should make sure to use the DATETIME2 data type instead of DATETIME.
That said, #RedFilter makes a good point - why are you relying on the time stamp when you can use the generated ID instead?
This feels wrong.
Other than the objectID, this is the only unique identifier
Databases have the concept of a unique identifier for a reason. You should really use that to retrieve an instance of your object.
You can use the get method on the Hibernate session and take advantage of the session and second level caches as well.
With your approach you execute a query everytime you retrieve your object.