I have an integer field in the DB (Postgresql) and my hibernate mapping file that I want to use in a like operation (e.g. Restrictions.like(Bean.fieldname,'123')).
The database does not support like for integer without explicit type casting select * from table where text(myint) like '1%'. Ideally, I'd like to keep the DB field type and Hibernate property type as integers and not have to load all the fields from the DB to iterate through in the Java code.
cheers :)
If the value really is a number, I'd just restrict it to a range - e.g. greater than or equal to 100 and less than 200. I wouldn't have thought you'd really want "all numbers starting with 1" - that suggests that 1 and 10000 are similar, whereas 1 and 2 are totally different. The information in a number should almost always relate to its magnitude, not the digits from its decimal representation.
Why do you need a LIKE? It's a very strange comparison, that's also why it's not an integer operator.
You could cast the value in the database to text/varchar, but you will kill performance unless you create a special index as well.
Restrictions.sqlRestriction("CAST({alias}.myint AS CHAR) like ?", "%1%", Hibernate.STRING));
Related
I have a table called "sector" which ID is Long instead of Integer. When I send a request from postman where I say that i want the entities from certain table where "anotherEntity.idSector = 1" it will give me an error.
Anfter several try/error I just discovered that this "1" is an integer for Postman, so when it gets to Java it gives me an error because expects a Long value.
So, is there a way to tell JSON that the value is a Long number? If it was a double, i would replace the "1" by "1.0" and it'd do, but with Long numbers?
Thanks in advance!
No, you can't "tell JSON" anything, it's just an encoding format. Like JavaScript, JSON has no integers, no longs, no floats and no doubles.
It has numbers: https://datatracker.ietf.org/doc/html/rfc8259#section-6
If you need more integer precision than JSON's number type provides, you would typically encode the number as a string. This is generally a good policy for fields like record IDs which are incidentally numeric, rather than semantically numbers (ie, you'll never perform numeric operations on them like addition or division).
When using SQL, I can run a simple query such as the query below with no issue, it returns an answer to 4 decimal places:
SELECT(COUNT(ID)/7) FROM myTable;
If the count above returns a value of 12, the returned select value is 1.7143 in workbench.
My issue occurs when I use jooq to do this calculation:
dsl.select(count(MYTABLE.ID).divide(7).from(MYTABLE).fetch();
The above code returns me a value of 1, whereas I want a value of 1.7143.
I have similar lines of jooq code which use SUM as opposed to COUNT and they return a value to 4 decimal places but I cannot find a way to get the above code to return the value to 4 decimal places.
I have tried using .round but had no success.
Has anyone else had a similar problem and knows of a solution?
There are two issues here, depending on what RDBMS you're using:
1. The type of the whole projected expression
The type of the whole division expression depends on the type of the left hand side (dividend), which is SQLDataType.INTEGER. So, irrespective of whether your RDBMS returns a decimal or floating point number, jOOQ will use JDBC's ResultSet.getInt() method to fetch the value, where you will be losing precision. So, the first step is to make sure jOOQ will fetch the desired data type. There are several ways to do this:
Use a cast on the COUNT(*) expression: count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7)
Use a cast on the entire expression:
count(MYTABLE.ID).divide(7).cast(SQLDataType.DOUBLE)
Use data type coercion on either expression: expr.coerce(SQLDataType.DOUBLE)
Casts have an effect on the generated SQL. Data type coercions do not.
2. How your RDBMS handles data types
In most RDBMS, count(*) expressions produce an integer type, and your division's right hand side (divisor) is also an integer, so the best resulting data type is, in fact, an integer type. I suspect you should pass a double or BigDecimal type as your divisor instead.
Solution
The ideal solution would then be to combine the above two:
dsl.select(count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7.0))
.from(MYTABLE)
.fetch();
I need to store a list of 1s and 0s in a single column on MySQL. For that column max length of the sequence for a cell will be 100.
On java side, after I fetch that data from MySQL, I need to convert it to something like EvictingQueue or any other appropriate data type. Because I need to add new values while the earliest entered one (1 or 0) will be popped from the list. Then I will update MySQL with new sequence.
What data type do you suggest me to use on MySQL for that column? Also do you have any other suggestion for Java side? So far, EvictingQueue looks logical to me.
Solution: I preferred using EvictingQueue on Java side and VARBINARY(100) on MySQL side. Works stable.
For MySQL, varchar type makes more sense as any numeric type may trim out leading zeros.
For java, I think we can have the value extracted as String and do bitwise shifting as explained here.
EvictingQueue is perfectly fine. However, I thought of providing another approach.
Currently im working in a project where we had recently a discussion about this. So lets have any database table with a numeric column which is allowed to have "no value" in the source code.
Some of my colleagues prefer to use the primitive type int in their mapped objects and set the value in this case to -1; i prefer to make this column nullable, using the Integer object in source instead of the primitive type and set this value to null.
Now im searching for the pro's and con's of both variants but couldn't find anything so far.
The only article i found so far is this one:
http://www.javapractices.com/topic/TopicAction.do?Id=134
...
There is a very common exception to this rule. For Model Objects, which map roughly to database records, it's often appropriate to use null to represent optional fields stored as NULL in the database
...
#EDIT
I need to add that such kind of columns are used in this project as a kind of fake foreign keys. They are not real database constraints but used as such. Dont ask me why...i know i know :-)
-1 in this case means it has no relationship to the primay key/id of another table. So its not needed for any calculations or such stuff...
For Nullable columns, it is preferred to have null value, when you don't want to store a value. Your approach of using Null Integer object is far better than -1
Consider this, your numeric column is being used in calculation and adding -1 (instead of null) could change the calculation. But, if you have Null your calculations would be correct
Pros of using Null Integer:
If numeric column is used in calculation, your output is not effected.
When using ORM, the underlying framework doesn't have to insert value in that column, if it's an insert query
Another benefit is that your DB would have less number of rows with -1 as value in nullable columns. (Think of 10 billion rows with -1 as a value for nullable column where you wanted to put null)
Since, both Integer and Null require 4 bytes of memory space, memory benefit can be claimed by using static null Integer object.
You don't have to check for -1 everywhere
The reason those guys still use int - primitive is may be they have not yet realized the benefit of using Objects over primitives or are still used to JDK 1.4 style coding
I hope I was able to answer your question...
I am attempting to delete a row, whose primary key(column name=version) for example is 4.002000000000001. So I give say the statement:
DELETE FROM tbl WHERE version=4.002;
Now right now this wont work, because theres no row that has a version equal to 4.002, only a row with a version equal to 4.002000000000001. Please dont ask why I dont store the version as 4.002 in the DB because I am trying to do so by making the column type DECIMAL(5,3) but it still stores a double from Java as 4.002000000000001. And please dont ask why I dont say "...WHERE version=4.002000000000001;" because right now I have no control over how java formats it doubles(even using DecimalFormat class) when I create a statement using JDBC.
So is there a way to round down(floor function) in SQLite3? So then I can say "delete the row whose FLOOR(version) is equal to 4.002?
I am a C++ programmer (using Java to query an SQL database, please dont ask why :P) who is not proficient with complex SQL queries, so would this be correct for what I want to do:
DELETE FROM tbl WHERE ROUND(version, 0.5)=4.002;
And please dont ask why I dont say "...WHERE version=4.002000000000001;" because right now I have no control over how java formats it doubles(even using DecimalFormat class)
I won't.
But I will ask why you are using double to store a version number.
Machine floating point types (base 2) do not hold exact decimal numbers. But version number strings are exact. You would be better off treating version "numbers" as one of the following, depending on your version numbering scheme:
Scaled integers; e.g. 4.002 is 4002 divided by 1000. You probably don't need to store the scaling factor explicitly.
Tuples or arrays of integers; e.g. 4.002 is {4,2}. This allows version numbers like 4.003.005 to be represented as {4,3,5} etcetera.
Character strings constrained by a pattern; e.g. 4.002 is a string that matches the regex "\d+\.\d\d\d". This allows version strings with non-numeric parts.
Choose one of those and you won't have to worry about the fundamental inexact nature of floating point types, in memory or in the database.
Oh, and by the way the DecimalFormat class does let you control the number of digits after the decimal place when you format a number. You can specify this using a pattern or by calling setMaximumFractionDigits
Can you do?
DELETE FROM tbl WHERE version > 4.002 - 1e-4 AND version < 4.002 + 1e-4
or
DELETE FROM tbl WHERE version > 4.0015 AND version < 4.0025
DELETE FROM tbl WHERE abs(version-4.002)<.0001
if you want to remove all versions in an epsilon boundary of .0001