Avoid Date Overlapping using JPA - java

I have an entity class with properties 'code','fromDate' and 'toDate' and i need to insert one new record using JPA such a way that for given code date range should not overlap.
For example
If code- ABC of date range 01/Feb/2014-10/Feb/2014 exist in DB.
I am inserting code ABC again with date range
03/Feb/2014-07/Feb/2014 should not accept - from date and to date is Within existing Date range
28/Jan/2014-02/Feb/2014 should not accept - to date is Within existing Date range
05/Feb/2014-21/Feb/2014 should not accept - From date is Within existing Date range
01/Jan/2014-28/Feb/2014 should not accept - The existing date range is within the given date range so Overlapping will happen.
Suppose the data need to be inserted is in a viewObject with similar properties.
Please help me to do the validation for date overlapping using JPA predicates

Before saving the new object you can query the DB to check if an 'overlapping' records exists.
If, a record is returned, then do not save the new object, else save;
String query = "SELECT ent FROM Entity ent WHERE ent.fromDate <= :toDate AND ent.toDate >= :fromDate WHERE ent.id = :entId";
List<Entity> overlappingRecords = JPA.em().createQuery(query).setParameter("entId", id).setParameter("fromDate", fromDate).setParameter("toDate", toDate).getResultList();
if(overlappingRecords.isEmpty())
//Over lap does not exist
else
//Over lap exists
This query assumes rejection of edges overlapping exactly.

Related

timestamp type changes to date type in hibernate query

I have an entity named A, which has a createdDate with this type #Temporal(TemporalType.TIMESTAMP).
I tried to retrieve all the rows having a certain createdDate. I attached a certain date to the request and I printed that date, it looks fine like "2021-02-11 12:14:02.425", which has all the values up to millisecond.
But the sql from hibernate, the value for createdDate in the where clause is set as '11-Feb-21'. Therefore, I do not find any rows because the createdDate is saved as 2021-02-11 12:14:02.425 in the db.
public Response getByCreatedDate(Request req) {
List<AResponse> aList = aRepository.findByIdAndCreatedDate(req.getId(), req.getCreatedDate());
}
I am new for Hibernate, I tried find some useful information about it but could not. Do I have to explicitly create a new Date with those specific date and time and send it to the method 'findByIdAndCreatedDate'? If anyone has the same experience, could you give some information about it?

db4o query optimisation for a scheduling application

I'm just getting started with db4o in a scheduling application and I'm looking for an efficient way to retrieve rooms which are not booked between certain dates.
So, I have a collection of Room objects each of which has a collection of Booking objects (which can be empty). A Booking has a start date and and end date. I want to say 'get all the rooms that have no Bookings between DateA and DateB'.
I'm sure I could do this using a Native Query but since there's a date range involved (my understanding is date ranges aren't optimzed for NQ) and I need to do this query very frequently (many times per second for potentially more 10,000 rooms - the majority of which have no Bookings) I'm looking for more efficient alternatives.
Is there a way to phrase this using SODA?
Or a better way to arrange my data model to get round this issue?
Yes you can do this by using SODA Query
Date fromDate = null ; // assign reservation start dat
Date toDate = null ; // assign reservation upto
Query query = db.query();
query.constrain(Booking.class);
query.descend ("fromDate").constrain ( fromDate ).greater().equal ().
and (query.descend ("toDate").constrain (toDate).smaller().equal());
ObjectSet<Booking> objectSet = query.execute();
Query for all of the rooms which do not have a booking between fromDate and toDate
Query query = db.query();
query.constrain(Room.class);
query.descend ("bookingStartDate").constrain ( fromDate ).greater().equal ().and
(query.descend ("bookingEndDate").constrain (toDate).smaller().equal()).not();
ObjectSet<Room> objectSet = query.execute();
See Also : Building SODA Queries

Database timestamps not matching

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.

Empty result set from a Compass Lucene query with Dates

I am using Compass to make queries on data inside in memory data structure. It works fine for searching String and enum values, now I want to search dates.
Search criteria are annotated by #SearchRestriction annotation. Example about someDate:
#SearchRestriction(path="fooBar.someDate" type = SearchRestrictionType.EQUAL)
String someDate;
At searchable data SomeDate is annotated like the following:
#SearchableProperty
Date someDate;
SomeDate inside the searchable data is generated with new Date();) and query String is given as 20120802.
Situation on debugger:
This code generates queries like this:
someDate:20120802
Here someDate is the name of the field I am looking for and 20120802 is a date in order yyyyMMdd.
Problem:
No results is returned, when this query is run. I get an empty list. The Date in query is the same as in the Date object.
What is wrong??
Is this wrong way to search Dates with Compass? I can find only range queries about Date, but a search with exact Date or part of exact Date I cannot find.
You need to specify the format for Searchable property [Date]
#SearchableProperty(format = "yyyyMMdd")
To some extent, it relates to Grails: Lucene, Compass Query Builder and date ranges

Restricting hibernate's eager fetch beyond DAO

I have my entities as ProductType,Product and ProductInventory.
I have a join query to fetch list of inventory for a specific date range which joins Product and ProductInventory. I've got list of object arrays which I have casted and set it ready.
Now from DAO I return the list of products.
In my layer above, if I execute product.getProductInventory() it is actually firing a query again getting all the inventory and not those inventory as got by the join.
final StringBuilder queryString = new StringBuilder(
"from Product As rsProduct left outer join rsProduct.inventoryList "
+ "as inventory where rsProduct.efDate <= :travelEndDate AND rsProduct.expDate >= :travelStartDate AND rsProduct.locatiion = :LOCN AND rsProduct.id in (:productsIdList) and inventory.bookDate between :startDate and :endDate");
Ex. Say travel start date is 20th Jan and travel end date is 21 Jan. I get only two records here which is perfect.
But after i return to other layer, if i say product.getInventory() it fetches all inventory irrespective of dates.
Can someone address this problem?
You should define a filter and enable it before accessing the collection.

Categories

Resources