how to use pg_column_size in hibernate? - java

I am trying to get the size of a row in a postgresql table, I found that pg_column_size would do the trick, but its not working with hibernate :
#Query("SELECT pg_column_size(t.*) as filesize FROM TABLE as t where name=:name")
int getSize(#Param("name") String name);
intellij is giving this error :
< operator > or AS expected, got '('
I guess the problem is that hibernate doesnt support specific postgresql queries, it only supports the basic sql queries.
so is there a way around this ? if not is there a way to get/estimate the size of a postgresql row in java ?

In order to use a built-in postgres function , you have to declare you JPA query as nativeQuery
you should first change query to native (hibernate will directly execute the query instead of jpa -> sql generation )
#Query(value="SELECT pg_column_size(t.*) as filesize FROM TABLE as t where name=:name",nativeQuery=true)
int getSize(#Param("name") String name);
Also be sur of the TABLE name to be correct .

Add nativeQuery = true after the native query.
#Query("SELECT pg_column_size(t.*) as filesize FROM users as t where t.name=:name",nativeQuery = true)
use above Query, Hope This will work.

Related

How to add date in mysql database from Hibernate/Spring Jpa

I use spring boot, and I want to add 1 year to a specific column in mysql database
String queryRecherche = "UPDATE myTable t SET t.dateDebut = DATE_ADD(t.dateDebut, INTERVAL 1 YEAR) WHERE.id = 3 ";
Query query = em.createQuery(queryRecherche);;
query.executeUpdate();
But I get the folowing error :
org.hibernate.query.sqm.ParsingException: line 1:66 no viable alternative at input 'DATE_ADD(t.dateDebut,INTERVAL1'
Have you please any suggestions to do this.
You're using Hibernate 6 (I can tell by the error message), so the correct HQL syntax to use is:
UPDATE MyEntity t SET t.dateDebut = t.dateDebut + 1 year WHERE t.id = 3
You had three errors in your query:
You referred to the name of a table instead of the name of an entity class in the UPDATE clause.
You used the unportable MySQL DATE_ADD function instead of the portable HQL date/time arithmetic described here.
The syntax of your WHERE clause was garbled.
Perhaps you meant for this to be a native SQL query, in which case you called the wrong method of Session. But there's no need to use native SQL for the above query. As you can see, HQL is perfectly capable of expressing that query.
You can use SQL directly, via createNativeQuery, or register a new function as shown in this example to call it from HQL

Spring JPA and JDBC Template - very slow select query execution with IN clause

I am trying to execute the following query from my Java project.
I am using MySQL and data store and have configured Hikari CP as Datasource.
SELECT iv.* FROM identifier_definition id
INNER JOIN identifier_list_values iv on id.definition_id = iv.definition_id
where
id.status IN (:statuses)
AND id.type = :listType
AND iv.identifier_value IN (:valuesToAdd)
MySQL connection String:
jdbc:mysql://hostname:3306/DBNAME?useSSL=true&allowPublicKeyRetrieval=true&useServerPrepStmts=true&generateSimpleParameterMetadata=true
When I execute this same query from MySQL workbench it returns results in 0.5 sec.
However when I do the same from JPA Repository or Spring JDBC Template its taking almost 50 secs to execute.
This query has 2 IN clauses, where statuses collection has 3 only items whereas identifierValues collection has 10000 items.
When I execute raw SQL query without named params using JDBC template it got results in 2 secs. However, this approach is suseptible to SQL injection.
Both JPA and JDBC Templete under the hood makes used of Java PreparedStatement. My hunch is the underlying PreparedStatement while adding large params set is causing performance issue.
How do I improve my query performance?
Following is the JDBC template code that I am using:
#Component
public class ListValuesDAO {
private static final Logger LOGGER = LoggerFactory.getLogger(ListValuesDAO.class);
private final NamedParameterJdbcTemplate jdbcTemplate;
#Autowired
public ListValuesDAO(DataSource dataSource) {
jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
public void validateListOverlap(List<String> valuesToAdd, ListType listType) {
String query = "SELECT iv.* FROM identifier_definition id " +
"INNER JOIN identifier_list_values iv on id.definition_id = iv.definition_id where " +
"id.status IN (:statuses) AND id.type = :listType AND iv.identifier_value IN (:valuesToAdd)";
List<String> statuses = Arrays.stream(ListStatus.values())
.map(ListStatus::getValue)
.collect(Collectors.toList());
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("statuses", statuses);
parameters.addValue("listType", listType.toString());
parameters.addValue("valuesToAdd", valuesToAdd);
List<String> duplicateValues = jdbcTemplate.query(query, parameters, new DuplicateListValueMapper());
if (isNotEmpty(duplicateValues)) {
LOGGER.info("Fetched duplicate list value entities");
} else {
LOGGER.info("Could not find duplicate list value entities");
}
}
EDIT - 1
I came across this post where other's faced similar issue while running select query using PreparedStatement on MS SQL Server. Is there any such property like "sendStringParametersAsUnicode" available in MySQL?
EDIT - 2
Tried enabling few MySQL Performance related properties. Still the same result.
jdbc:mysql://localhost:3306/DBNAME?useSSL=true&allowPublicKeyRetrieval=true&useServerPrepStmts=true&generateSimpleParameterMetadata=true&rewriteBatchedStatements=true&cacheResultSetMetadata=true&cachePrepStmts=true&cacheCallableStmts=true
I think should enable "show_sql" to true in JPA and then try, I think its running multiple queries because of lazy loading because of which it may be taking time.
Composite indexes to add to the tables:
id: INDEX(type, status, definition_id)
id: INDEX(definition_id, type, status)
iv: INDEX(identifier_value, definition_id)
iv: INDEX(definition_id, identifier_value)
For jdbc, the connection parameters should include something like
?useUnicode=yes&characterEncoding=UTF-8
For further discussion, please provide SHOW CREATE TABLE for each table and EXPLAIN SELECT... for any query in question.
Instead passing the list to IN clause, pass the list as comma seperated string and split it in the query using
select value from string_split(:valuesToAdd, ',')
So your query will look like this
SELECT iv.* FROM identifier_definition id
INNER JOIN identifier_list_values iv on id.definition_id = iv.definition_id
where id.status IN (:statuses) AND id.type = :listType AND iv.identifier_value
IN (select value from string_split(:valuesToAdd, ','))
string_split is a function in SQL Server, MySQL might have similar one

Distinct and List of other column in postgresql

I am using postgres DB and i have table with two column name and sal .
name Sal
Raunak 10000
Raunak 5000
Rahul 500
Raunak 300
And i want
Raunak 10000,5000,300
Rahul 500
i am using JPA is there any way to get in JPA data
You can use string_agg function to build a comma separated list of values:
select name, string_agg(sal::text, ',')
from t
group by name
You might want to consider json_agg instead of csv if your application can consume json data.
If you want to preserve the data type of the sal column, you can use array_agg() that returns an array of values. Not sure if JPA will let you access that properly though
select name, array_agg(sal) as sals
from the_table
group by name;
If I understand your question correctly, you want to get the result via below SQL statement:
SELECT
name,
string_agg (sal::varchar(22), ', ') as sals
FROM
test
GROUP BY
name;
Since it's postgresql related SQL, we can't or hard to express it via common object query. You can construct the above SQL via native query mode in your JPA code.
#Query(value = "<the above query>", nativeQuery = true)
List<Object[]> query();

Convert complex DB2 SQL with ROW_NUMBER() to mongo query

I'm new to MongoDB, I'm trying to convert existing DB2 query to MongoDB. I'm Using Java to run this query.
Current DB2 Query:
SELECT * FROM
(SELECT MBI.*, ROW_NUMBER() OVER Order by PDATE DESC AS rownumber
FROM USER1.COLLECTION1 MBI, USER1.COLLECTION2 IC
WHERE MBI.VISIBILITY = 1 and MBI.MBOXID = '1234'
AND UPPER(MBI.MBOXITID) >= '1234555'
AND UPPER(MBI.CATEGORY) = 'S'
AND UPPER(MBI.Mimetype) = 'PDF'
AND UPPER(MBI.Psystemid) = 'TBA'
AND days(current date) - days(MBI.PDATE) < 20
AND MBI.MBOXITID = IC.ICONTENTID) AS FinalResult
WHERE rownumber BETWEEN 1 and 2 Order by PDATE DESC
Am really not sure how to get the ROW_NUMBER details in MongoDB.
Can you help for me solve problem?
#bharathiraja, hopefully, you've done the migration by now and figured out the steps. you'll have to convert your inner joins to mongodb lookup operator and then remove nulls (because lookup is left-outer-join-operator). From your query, looks like you're trying to paginate using row_number(). In Mongodb aggregation framework, after you've done the sort on the PDATE, you can add the limit and skip operator to paginate.
At Couchbase (where I work), we've built row_number() just like standard SQL. Checkout. https://blog.couchbase.com/on-par-with-window-functions-in-n1ql/

jOOQ problems with limit..offset - no values sets

I am trying to build a query using jOOQ, this is my test code:
DSLContext create = DSL.using(SQLDialect.DERBY);
String query = create.select().from(TABLE).limit(1).offset(0).getSQL()
I get as query:
select field1, field2...fieldN etc from TABLE offset ? rows fetch next ? rows only
the problem is ? in ? rows fetch next ? rows only it seems to ignore the values that i used in limit and offset to build the query, why?
I am trying to select the first row from the results and I am using jooq 3.4.1
Thanks for the help
Query.getSQL() returns your SQL string with ? as placeholders for your bind variables. The idea is that you can feed this statement to a PreparedStatement and then explicitly bind all variables, which are available through Query.getBindValues().
You can also have jOOQ inline all your bind variables, by calling Query.getSQL(ParamType) as such:
String sql = query.getSQL(ParamType.INLINED);

Categories

Resources