bit functions in HibernateEntityQuery - java

Is it possible to use bit functions in queries using Seam's HibernateEntityQuery?
I've just inherited some code based on JSF, Seam & Hibernate. The existing DAO code makes use of Seam's HibernateEntityQuery, in particular its support for restriction expression strings.
This has worked fine so far, but now I'm tasked with adding a restriction to an existing query that takes into account a bit field.
The Java entity code is using an integer field to represent a set of "days", via this enum:
public enum WEEKDAY {
MONDAY(1), TUESDAY(2), WEDNESDAY(4), THURSDAY(8), FRIDAY(16), SATURDAY(32), SUNDAY(64) ;
private int value;
private WEEKDAY(int value) {
this.value = value;
}
}
The integer value from this enum is stored into the entity in an int days field.
For example, if the entity contains MONDAY, WEDNESDAY AND FRIDAY, days would be set to 1 | 8 | 16, which == 25.
Now I'd like to add a new restriction to the query so that (for example) I can ask for entities where days includes MONDAY OR SATURDAY: 1 | 32 == 33, so in SQL, I would do:
select id from entity where (select days & 33) > 0;
Is there such a syntax for HibernateEntityQuery? I tried adding the following restriction:
entity.days & #{myQuery.bitwiseMeetingDays} > 0
which results in the following error:
org.hibernate.QueryException: unexpected char: '&'

I ended up refactoring the table to have 7 boolean fields rather than a single integer for "days". This makes command-line queries easier as well.
It would still be nice to know of a way to handle the bit-field query though.

Related

Getting form DB XXX.0E0 ( XX stand for a number)

I'm trying to query select statements using JDBCTamplate.
select statement:
SELECT currency, SUM(amount) AS total
FROM table_name
WHERE user_id IN (:userIdList)
GROUP BY currency
DB Table has three columns:
user_id
currency
amount
table for example
user_id currency amount
1 EUR 9000
2 EUR 1000
3 USD 124
When I'm trying to run this code
namedParamJDBCTemplate.query(query,
new MapSqlParameterSource('user_id', userIdList),
new ResultSetExtractor<Map>() {
#Override
public Map extractData(ResultSet resultSet) throws SQLException, DataAccessException {
HashMap<String,Object> mapRet = new HashMap<String,Object>();
while(resultSet.next()){
mapRet.put(resultSet.getString("currency"), resultSet.getString("total"));
}
return mapRet;
}
});
I'm getting the result set as a map, but the result of the amount looks like this :
EUR -> 10000.0E0
USD -> 124.0E0
When I run the same query in DB ( not via code) the result set is fine and without the '0E0'.
How can I get only EUR -> 10000 and USD-> 124 without the '0E0'?
.0E0 is the exponent of the number, as I think. So 124.0E0 stands for 124.0 multiplied with ten raised to the power of 0 (written 124 x 10^0). Anything raised to the power of 0 is 1, so you've got 124 x 1, which, of course, is the right value.
(If it was, e. g., 124.5E3, this would mean 124500.)
This notation is used more commonly to work with large numbers, because 5436.7E20 is much more readable than 543670000000000000000000.
Without knowing your database background, I can only suppose that this notation arises from the conversion of the numeric field to a string (in result.getString("total")). Therefore, you should ask yourself, if you really need the result as a string (or just use .getFloat or so, also changing your HashMap type). If so, you still have some possibilities:
Convert the value to a string later → e. g. String.valueOf(resultSet.getFloat("total"))
Truncate the .0E0 → e. g. resultSet.getString("total").replace(".0E0", "") (Attention, of course this won't work if, for some reason, you get another suffix like .5E3; it will also cut off any positions after the decimal point)
Perhaps find a database, JDBC or driver setting that suppresses the E-Notation.

BigQuery WORM work-around for updated data

Using Google's "electric meter" example from a few years back, we would have:
MeterID (Datastore Key) | MeterDate (Date) | ReceivedDate (Date) | Reading (double)
Presuming we received updated info (Say, out of calibration/busted meter, etc.) and put in a new row with same MeterID and MeterDate, using a Window Function to grab the newest Received Date for each ID+MeterDate pair would only cost more if there is multiple records for that pair, right?
Sadly, we are flying without a SQL expert, but it seems like the query should look like:
SELECT
meterDate,
NTH_VALUE(reading, 1) OVER (PARTITION BY meterDate ORDER BY receivedDate DESC) AS reading
FROM [BogusBQ:TableID]
WHERE meterID = {ID}
AND meterDate BETWEEN {startDate} AND {endDate}
Am I missing anything else major here? Would adding 'AND NOT IS_NAN(reading)' cause the Window Function to return the next row, or nothing? (Then we could use NaN to signify "deleted".)
Your SQL looks good. Couple of advices:
- I would use FIRST_VALUE to be a bit more explicit, but otherwise should work.
- If you can - use NULL instead of NaN. Or better yet, add new BOOLEAN column to mark deleted rows.

Comparing Date type in Oracle PACKAGE does not work

I made a Oracle Package like below.
And I will pass parameter String like '2014-11-05'.
--SEARCH 2014 11 04
FUNCTION SEARCHMYPAGE(v_created_after IN DATE, v_created_before IN DATE)
return CURSORTYPE is rtn_cursor CURSORTYPE;
BEGIN
OPEN
rtn_cursor FOR
select
news_id
from
(
select
news_id,
news_title, news_desc,
created, news_cd
from
news
)
where
1=1
AND (created BETWEEN decode(v_created_after, '', to_date('2000-01-01', 'YYYY-MM-DD'), to_date(v_created_after, 'YYYY-MM-DD'))
AND (decode(v_created_before, '', sysdate, to_date(v_created_before, 'YYYY-MM-DD')) + 0.999999));
return rtn_cursor ;
END SEARCHMYPAGE;
I confirmed my parameter in Eclipse console Message, since I am working on Eclipse IDE.
I got contents, which are made in 2014-10-29 ~ 2014-10-31.
when I pass '2014-11-01' as created_after, It returns 0 records.(But I expected all contents, since every contents are made between 10-29 and 10-31)
Would you find anything wrong with my Function?
Thanks :D
create function search_my_page(p_created_after in date, p_created_before in date)
return cursortype
is rtn_cursor cursortype;
begin
open rtn_cursor for
select news_id
from news
where created between
nvl(v_created_after, date '1234-01-01')
and
nvl(v_created_before, sysdate) + interval '1' day - interval '1' second;
return rtn_cursor;
end search_my_page;
/
Changes:
Re-wrote predicates - there was a misplaced parentheses changing the meaning.
Replaced to_date with date literals and variables. Since you're already using ANSI date format, might as well use literals. And date variables do not need to be cast to dates.
Replace DECODE with simpler NVL.
Removed extra parentheses.
Renamed v_ to p_. It's typical to use p_ to mean "parameter" and v for "(local) variable".
Removed extra inline view. Normally inline views are underused, in this case it doesn't seem to help much.
Removed unnecessary 1=1.
Replaced 0.99999 with date intervals, to make the math clearer.
Changed to lower case (this ain't COBOL), added underscores to function name.
Changed 2000-01-01 to 1234-01-01. If you use a magic value it should look unusual - don't try to hide it.

Count number of days between 2 dates in JPA

I need to count the number of days between 2 dates in JPA.
For example :
CriteriaBuilder.construct(
MyCustomBean.class
myBean.get(MyBean_.beginDate), //Expression<Date>
myBean.get(MyBean_.endDate), //Expression<Date>
myDiffExpr(myBean) //How to write this expression from the 2 Expression<Date>?
);
So far, I tried :
CriteriaBuilder.diff(). but it does not compile because this method expects some N extends Number and the Date does not extend Number.
I tried to extend the PostgreSQL82Dialect (as my target database is PostgreSQL) :
public class MyDialect extends PostgreSQL82Dialect {
public MyDialect() {
super();
registerFunction("datediff",
//In PostgreSQL, date2 - date1 returns the number of days between them.
new SQLFunctionTemplate(StandardBasicTypes.LONG, " (?2 - ?1) "));
}
}
This compiles and the request succeeds but the returned result is not consistent (78 days between today and tomorrow).
How would you do this?
It looks like you are looking for a solution with JPQL to perform queries like SELECT p FROM Period p WHERE datediff(p.to, p.from) > 10.
I'm afraid there is no such functionality in JPQL so I recommend using native SQL. Your idea if extending Dialect with Hibernate's SQLFunctionTemplate was very clever. I'd rather change it to use DATE_PART('day', end - start) as this is the way to achieve days difference between dates with PostgreSQL.
You might also define your function in PostgreSQL and using it with criteria function().
'CREATE OR REPLACE FUNCTION "datediff"(TIMESTAMP,TIMESTAMP) RETURNS integer AS \'DATE_PART('day', $1 - $2);\' LANGUAGE sql;'
cb.function("datediff", Integer.class, end, start);
JPA 2.1 provides for use of "FUNCTION(funcName, args)" in JPQL statements. That allows such handling.
I finally found that the problem comes from the fact that the order of the parameters is not the one I expected :
/*
*(?2 - ?1) is actually equivalent to (? - ?).
* Hence, when I expect it to evaluate (date2 - date1),
* it will actually be evaluated to (date1 - date2)
*/
new SQLFunctionTemplate(StandardBasicTypes.LONG, " (?2 - ?1) "));
I opened a new question in order to know if this behavior is a bug or a feature :
1) CriteriaBuilder.diff(). but it does not compile because this method expects some N extends Number and the Date does not extend Number.
Try to use no of mili seconds for each date as shown below.
Date date = new Date()//use your required date
long millisecond = date.getTime();//Returns no of mili seconds from 1 Jan, 1970 GMT
Long in Number in java and according to autoboxing you can use this. May be this can help.

How to store a java object with variable number of attributes

I've looked at How to store data with dynamic number of attributes in a database, but it didn't quite answer my question. The system I am implementing is rather large, so I'll stick with the objects I am concerned about: Item and Category. An Item has a variable number of attributes depending on the Category that it belongs to. For instance, Items belonging to the "T-shirt" Category would have an attribute for size, while Items belonging to the "Car" Category would have an attribute for model. Someone logged into the system as an Admin can create new Categories with completely new attributes. What's the best way to structure this both in my Java code and in my database to make this work?
If the categories weren't dynamically created, I'd use inheritance so that I would have a TShirtItem object with its specific attributes filled in. But since it is dynamic, I'm puzzled. I saw a similar question that suggested using the Map data structure, but I am not sure how that would work...
The question I referred to at the top would suggest on the database end that I would have an Category table, and Attributes table, and relationship table linking what attributes go with what Category. This makes sense. But I'm tripped up again when thinking about the Item object. I could store the unique Category_ID in the Item table, but where would I store the attributes for each Item?
If you are constrained to use an SQL database and you need to do efficient type-aware (not merely string) queries on the attributes (like list all items with category shirt having size between 4 and 8), then the structure of the database is the hard part. The Java will follow from that. If I understand correctly, you will need something like this:
categories:
id : integer (pk)
name : varchar
attributes:
id : integer (pk)
of_category : integer (fk -> categories.id)
name : varchar
type : char(1) // 'N' for number, 'S' for string, etc.
items:
id : integer (pk)
of_category : integer (fk -> categories.id)
number_values:
value : number
of_item : integer (pk, fk -> items.id)
of_attribute : integer (pk, fk -> attributes.id)
string_values:
value : varchar
of_item : integer (pk, fk -> items.id)
of_attribute : integer (pk, fk -> attributes.id)
... additional table for each attribute type
Now for the example query:
select * from categories c, items i, attributes a, number_values v
where c.name = 'shirt' and
a.of_category = c.id and
a.name = 'size' and
a.id = v.of_attribute and
i.id = v.of_item and
v.value between 4 and 8
Hairy multiple joins are the price to be paid for runtime-defined attrbutes.
Once you have the tables right, modeling them as Java maps is straightforward. There is redundancy in the structure above: for example the character "type" field in the attribute rows. Consider triggers to make consistency checks.
Here is a simple java approach to do it. While designing large systems I always suggest to look at the bigger picture. The issue here is dynamically changing attributes. It would not be easy but yeah it is interesting.
The structure of your item class has to be like the following:
class Item{
private String itemName; // I assume all items will have a name.
private Map<ItemAttibuteName , Object> attributeMap ; // this will be a dynamic map.
public Map<ItemAttibuteName, Object> getAttributeMap(){//getter for attribute map
if( null == attributeMap)
return new HashMap<String, Object>();
return attributeMap ;
}
// you can synchronize this if needed
public void setAttribute(ItemAttibuteName name, Object value){
attributeMap.put(name, value);
}
public Object getAttribute(ItemAttibuteName name){
return attributeMap.get(name);
}
}
public enum ItemAttibuteName{
SIZE,
COLOUR
}
This approach suites your needs, further you can use a factory pattern to instantiate the Items depending on the category and make it an elegant code.
Please get back if you still have some doubts.
EDIT:
Now there will be a complicated way to get all the attributes of an element in the code while programming, because you don't have getters or setters for the attributes. Well, the approach will help if you can maintain a Set of attributes added to the Item, in the Item class or you can query for the keySet of the item class's attributeMap property.
private Set<ItemAttibuteName> attributes;
or
attributeMap.keySet();
Happy to Help
Dharam
Instead of Java it is more of design level issue. You have to figure out the way to define DB tables and that will assist you in finding the Java objects...
Lets start from category... A category may contain lot of Items, and an Item will belong only one category(Though I practical scenarios it is not a correct assumption).
So in DATABASE you have table called Category. If you wanna define attribute based on category, then have another table called Category_attribute which will hold default value for the attribute.
Now lets move to an Item. An item belongs to a Category so Item table will have category_key to have the mapping for Item n category... Item will have its attribute which are stored in ITEM_Attribute table...
Simple form of DB objects must be somewhat as mentioned below
Category
C_Id
Name
Category_Attribute
CA_ID
Name
Default_value
Category_Id(FK)
Item
I_ID
Name
C_ID(FK)
Item_attribute
IA_ID
Ca_ID(FK from category_attribute table)
I_ID(FK from item table)
Value
So whenever you create a Category, you will ask user to define associated attribute to the category.
At the time of creating the Item, you map it to category... And attributes associated to category should replicate with default value and map to item as well...
So you will be able to create Java objects easily...
I guess you can structure ur data in such a way that u define all object types in a table
and later use the below approach.
U can define tables like:
OBJECT_TYPE
OBJECTS
OBJ_PROPERTY_DEF
OBJ_PROP_VALUES
eg.
In OBJECT_TYPE
Define all object types here
object_type_code(pk) obj_name
4 car
5 t-shirt
In OBJECTS
obj_code(pk) object_type_code(fk) obj_name
1 4 BMW
2 4 Maruti
3 4 Honda
4 5 levis
5 5 polo
6 5 reebock
In OBJ_PROPERTY_DEF
Define all properties corresponding to a object in this table.
Note: Using Constants file to deifine property types would avoid another table.
Hopefully when you know the data types earlier.
obj_prop_code(pk) obj_code(fk) property_type property_name
------------- -------- ------------- -------------
12 6 8 (Integer) size
13 6 9 (String) color
14 6 10 (float) weight
15 6 11 (Boolean) is_coloured
16 6 9 (String) comments
17 3 9 (String) model
18 3 8 (Integer) version
19 3 9 (String) color
20 3 9 (String) comments
In OBJ_PROP_VALUES
U can inser the values the the above specified properties
obj_prop_val_code(pk) obj_prop_code(fk) obj_prop_value(VARCHAR) prop_value_sufix
----------------- ------------- -------------- -----------------
101 12 30 -
102 13 green -
103 14 126 gms
104 15 0 -
105 16 looks cool -
106 17 c532 -
107 18 3.22 -
108 19 black -
109 20 awesome car -
Reg Java classed:
Define all classes with corresponding properties.
eg:
ObjectTypeData
ObjectData
ObjectPropertyDefData
ObjectPropertyValuesData
In ObjectData.java
private ObjectTypeData objType;//specifies the type
private List<ObjectPropertyValueData> listProps; //will have all property values
//setter & getters and other req props
I think some attributes are major(size, color...) and some are minor(material, weight....). I will describe simplified JDL schema for this(of course exist another Stock entity which stores exact item with color, size - identified with barcode - but omitted for simpilicity). This design will help, not hard coding some part of attributes which is important for classifaing items.
Using this design Adding Data
For creating data in this design => You are creating some category with it's attribute, size type(for example Shoes => 39,40,41...(options); Tshirt => S,M,L..., Iphone 7,8,X...) => inside this category particular Article - Iphone (with this way on your E-Commerce system exist Iphone)
You adding specific Article Iphone X (size) - Color Black to your warehouse or stock with additional Category related Attributes => Material, Weight .... and system generates for you barcode. With this way you can easily specify Iphone with sizes and colors(without additional sql - with pure ORM) (even with additional attributes)
enum CategoryTarget{
F, M, K
}
entity Category{
name String,
imageUrl String,
showHomepage Boolean,
target CategoryTarget,
accOrder Integer,
isLastNode Boolean
}
entity Article{
status Integer,
name String,
code String,
rating Double,
imageUrl String,
isPopular Boolean
}
relationship ManyToOne{
Category{parent} to Category,
Article{category} to Category{article},
Category{sizeType} to SizeType
}
relationship ManyToMany{
Category{attribute} to Attribute{category}
}
entity Attribute{
name String
}
entity AttributeOption{
name String
}
relationship OneToMany{
Attribute{attributeOption} to AttributeOption{attribute}
}
entity SizeType{
name String
}
entity ArticleSize{
name String,
accOrder Integer
}
relationship OneToMany{
SizeType{articleSize} to ArticleSize{sizeType}
}
relationship ManyToMany{
Article{attributeOption} to AttributeOption{article}
}

Categories