I want to insert array of custom type into postgres with jdbc.
my sql schema:
CREATE TYPE element_pk_t AS (
workspace_id BIGINT,
element_id BIGINT,
history_id BIGINT
);
my java class:
public class ElementPK {
public Long workspaceId;
public Long elementId;
public Long historyId;
}
How should I do this in java with jdbc?
I've found tutorial regarding custom type https://docs.oracle.com/javase/tutorial/jdbc/basics/sqlcustommapping.html, but array of custom type is still unclear to me.
One trivial approach is using pure string style SQL statement, but I still prefer using PreparedStatement with setObject or setArray
If I understood you correctly, then, from the Java code, you need to generate query that looks, for example, like this:
INSERT INTO parent_table(elements)
VALUES (
ARRAY[
row(1, 2, 3)::element_pk,
row(4, 5, 6)::element_pk,
row(7, 8, 9)::element_pk
]);
Assuming that you have a table like the following:
CREATE TABLE parent_table(
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
elements element_pk[]
)
And the Type like you described. If I were you, I wont implement it via an array. I would have use JSONB instead - in this way you wont lose an ability to use indexing. Of course, there is java.sql.Array out there, and you can still do it via the following:
Array array = connection.createArrayOf("public.element_pk", new ElementPK[]{
new ElementPK(1, 2, 3),
new ElementPK(9, 4, 6)
});
And then set the array, to PgPreparedStatement, but the thing is that internally PgPreparedStatement will enclose your elements within curly braces, which is ok, but each element will be represented by its toString method call result. I mean, assume your ElementPK toString looks like this:
#Override
public String toString() {
return "This is how it is implemented, really?";
}
then you will get the SQL like:
INSERT INTO parent_table (elements) VALUES ('{"This is how it is implemented, really?","This is how it is implemented, really?"}')
Again, it is maybe possible to adopt it, but from my perspective - at least having your logic within toString method is not that great, is it? Spare yourself and do the following:
CREATE TABLE via_jsonb(
elements JSONB
);
and then simply:
INSERT INTO via_jsonb VALUES(
'{
"workspace_id" : 1,
"element_id" : 2,
"history_id" : 3
}'
);
and in the Java code I would have simply create json from your object and set it as a string. Really, there are a lot of functions and cool features on JSONB out of the box.
Hope it helped, have a nice day!)
Follow up to the last part of #misha2045 answer.
If you still refuese to use JSONB for whatever reason you need to add parenthesis at the end and start of your toString method.
#Override
public String toString() {
return "("+this.field1+ ", " + this.field2+")";
}
Then set the array in the prepared statement
ps.setArray(1, con.createArrayOf("yourType", yourClassArray));
I have next method in JPA Repository kartDao:
#Query(value = "select t.k_lsk_id from SCOTT.KART t ", nativeQuery = true)
List<Integer> findAllKlskId();
When I try to fetch it using:
List<Integer> someLst = new ArrayList<Integer>();
someLst.add(12); // my Integer value
someLst.addAll(kartDao.findAllKlskId());
I see in debugger that someList contains both Integer and BigDecimal types:
But how it happens? My someList is List type!!
Can't understand, help me))
upd1
In Oracle database the k_lsk_id type is Number:
The culprit is this line of code I think.
It tries to convert the result of the query execution.
If it fails to find a converter it just returns the original unconverted result.
The converter used is essentially a DefaultConversionService which doesn't support any convertions from BigDecimal.
UPDATE: I looked a little more into this, and it seems that the problem is not so much that the conversion service can't convert BigDecimal, but that the requested target type is simply List.
I opened an issue and will look into it.
Number return decimal value form the DB side.
you should have to change the number to Integer
I am trying to query DynamoDB using mapper.query() function with FilterExpression.
I need to generate a generic function where I will just tell the attributes operator and value, and it will return the generic string. But I see, it is not completely possible.
new DynamoDBQueryExpression<T>()
.withFilterExpression("att = string_val")
This is possible but if I have an Integer filter, then I have to do like this :
new DynamoDBQueryExpression<T>()
.withFilterExpression("att = :filter")
.withValueMap(":filter", new AttributeValue().withN(String.valueOf(12)));
Can this be avoided ? I wish to put everything in the filter string.. Can dynamoDB itself recognise int/string attributes ?
Thanks in advance!
I'm trying to create a query with selects only the Entities with specific numeric value in their property but the following Filter returns an empty result
Filter tmpFilter = new Query.FilterPredicate("cost", Query.FilterOperator.EQUAL, 10);
I have several entities that should be selected, I have tried to send the "10" as a string but still no luck.
When I try to select with GREATER_THAN or other filter operators then it works.
I have tried to run EQUAL on a string value and it worked but not on a numeric value.
Any ideas ?
Integer values are stored as Long in the Datastore. Try 10L instead of 10.
I need to optimize a query that iterates over several objects and I wanted Spring Data to let the database handle it. I want to end up with a HashMap<String,String> that looks like
2134_9877, 9877
2134_2344, 2344
3298_9437, 9437
The SQL would be select convert(varchar,b.id)+'_'+convert(varchar,a.id)',a.id from t1 a join t2 b on a.jc = b.jc
So far, I've got Whatever-QL in the repository that looks like:
#Query("SELECT new map (a.bkey, a.akey) FROM mergeTable a WHERE a.discr= ?1")
The problem is, bkey is not unique, it is only unique when paired with akey and the monstrosity that I have to feed it to wants them combined with an underscore: 2345_2177.
I have tried a.bkey.toString and ''+a.bkey and new String(a.bkey) and just string(a.bkey) (that last gives a new exception but still doesn't work) but Spring doesn't like any of these. I can find no questions asking this and it seems I cannot use SQLServer's convert() function as this ain't SQL.
How can I concatenate the Integers as Strings with an underscore in this #Query?
PS: Using the native query that's been debugged in SQLServer throws some weird alias exception in Hibernate so I think 'going native' is predetermined to be a dead end.
If I have understood it right, the 'Whatever-QL' is called JPQL, and the operator CONCAT can be used. Only the use of it, as it accepts two or more parameters depends on the JPA version you are running.
Here is the answer.
JPA concat operator
You could add a getter to your entity like this:
public String getCombinedKey(){
return a.akey + "_" + a.bkey;
}
The advantage is you could handle here null's and other things if you want and it's more reusable in case you need this in another place. If you do it just in the repository you will have to copy it everytime.
Your query would then be:
#Query("SELECT new map (a.combinedKey, a.akey) FROM mergeTable a WHERE a.discr= ?1")