I am working on a spring boot application that queries a large set of data from the db and is need to be processed in my application.
I am using #SqlRessultSetMapping in the entity class but getting org.hibernate.MappingException: Unknown SqlResultSetMapping every time the query runs.
below is the example of how i am mapping the columns.
#SqlResultSetMapping(
name = "QueryResultMapping",
entities = #EntityResult(
entityClass = AwaitingCancellationModel.class,
fields = {
#FieldResult(name="Colum1_Key",column = "Colum1Value"),
#FieldResult(name="Colum2_Key",column = "Colum2_Value"),
#FieldResult(name="Colum3_Key",column = "Colum3_Value"),
#FieldResult(name="Colum4_Key",column = "Colum4_Value"),
#FieldResult(name="Colum5_Key",column="Colum5_Value"),
#FieldResult(name="Colum6_Key",column = "Colum6_Value"),
#FieldResult(name="Colum7_Key",column = "Colum7_Value")
}
)
)
and the query is being made as List<ClassModel> queryResult = entityManager.createNativeQuery(sqlQuery,"QueryResultMapping").getResultList();
i have a nested query as part of sqlQuery.
Any help is appreciated! Thanks!
Related
Hi what I trying to achieve is to to get returned result of Page the result get in into DTO and request as Pageable. How do I do this properly?
I found couple way but I am not sure and not comfy about it. I every try QueryDsl way, but it have "count" limitation when using aggregate function like sum() with group By with multiple column right now will write nativeQuery with #Query() annotation in my repository, which is will be looked like this:
#Query(name = "find_stock_total", nativeQuery = true)
Page<StockTotalResponseDto> findStockTotalRsMap(Pageable pageable);
Then in my entity class, I have to write #NamedNativeQueries and mapped it with #SqlResultSetMappings, here is how I write it:
#NamedNativeQueries({
#NamedNativeQuery(
name = "find_stock_total",
query = "SELECT product_id, product_code, sum(qty) FROM "book_stock"
where warehouse_code = 'GBKTJKT1' and product_code in('MCM-508','TL-101') and branch_code = 'JKT' and branch_id = '1'
GROUP BY product_id, product_code",
resultSetMapping = "stock_total_response_dto"
),
#NamedNativeQuery(
name = "find_stock_total.count",
query = "select count(*) from (
SELECT product_id, product_code, sum(qty) FROM "book_stock"
where warehouse_code = 'GBKTJKT1' and product_code in('MCM-508','TL-101') and branch_code = 'JKT' and branch_id = '1'
GROUP BY product_id, product_code
) as count"
)
})
#SqlResultSetMappings({
#SqlResultSetMapping(
name = "stock_total_response_dto",
classes = #ConstructorResult(
targetClass = StockTotalResponseDto.class,
columns = {
#ColumnResult(name = "product_id", type = String.class),
#ColumnResult(name = "product_code", type = String.class),
#ColumnResult(name = "sum", type = BigInteger.class)
}
)
),
#SqlResultSetMapping(
name = "stock_total_response_dto.count",
columns = #ColumnResult(name = "count")
)
})
#Entity
I will have to write sql string in a #Entity class and I can't use Sort that provided by Pageable and I have to write extra Count query. I want to use Pageable Sort, to sort my data. is there another way to write something like that in better way or maybe modern way? Maybe someone can provide "Criteria" way or there is another Jpa way? Or something better than this?
You should checkout what Blaze-Persistence has to offer which works on top of JPA/Hibernate and also has an integration with spring-data-jpa which allows you to use it as a drop-in replacement for what spring-data-jpa does normally.
It supports aggregation functions properly (also for count queries), has support for keyset pagination and much more. Checkout the documentation about the Spring Data integration: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/#spring-data-integration
I've a database with many thousands of tables that have been (and continue to be) created with a naming strategy - one table per calendar day:
data_2010_01_01
data_2010_01_02
...
data_2020_01_01
All tables contain sensor data from the same system in the same shape. So a single entity (lets call it SensorRecord) will absolutely map to all tables.
I'd imagined something like this would work:
#Query(nativeQuery = true, value = "SELECT * FROM \"?1\"")
Collection<SensorRecord> findSensorDataForDate(String tableName);
But it does not, and reading around the topic seems to suggest I am on the wrong path. Most posts on dynamic naming seem to state explicitly that you need one entity per table, but generating thousands of duplicate entities also seems wrong.
How can I use JPA (JPQL?) to work with this data where the table name follows a naming convention and can be changed as part of the query?
Parameters are only allowed in the where clause.
You can create custom repository method returns collection of SensorRecord dto. No need to map so many entities. You should get List<Object []> as query result and manually create dto objects.
#Autowired
EntityManager entityManager;
public List<SensorRecord> findSensorDataForDate(LocalDate date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd");
String tableName = "data_" + date.format(formatter);
Query query = entityManager.createNativeQuery(
"select t.first_column, t.second_column from " + tableName + " t");
List<Object[]> queryResults = query.getResultList();
List<SensorRecord> sensorRecords = new ArrayList<>();
for (Object[] row : queryResults) {
SensorRecord record = new SensorRecord();
record.setFirstParameter((Integer) row[0]);
record.setSecondParameter((String) row[1]);
sensorRecords.add(record);
}
return sensorRecords;
}
Could it be just syntax error?
This has worked for me:
#Query(value = "select * from job where job.locked = 1 and job.user = ?1", nativeQuery = true)
public List<JobDAO> getJobsForUser(#Param("user") String user);
I have issues injecting the database schema to my #ColumnTransformer, eg
#ColumnTransformer(
read = "(select trim(sct.CD) from {h-schema}SCT sct where sct.CD_TBL_ID = 4 and sct.CSN = KEY_VAL_TCSN)"
)
Does not resolve the {h-schema}, but instead it translates to
(select trim(sct.CD) from {h-kvlist0_.schema}VTKC028_SCT kvlist0_.sct where sct.CD_TBL_ID = 4 and sct.CSN = kvlist0_.KEY_VAL_TCSN)
I am trying to resolve crossreference of KEY_VAL_TCSN from SCT.CD table.
So it replaces the {h-schema} with {h-kvlist0_.schema} instead of the query schema.
Usually during my work hours i spend a lot of time querying the db(oracle) and parsing blob from various table where the streams that we receive are stored.
There are various type of stream so i was trying to made a simple webapp where i write the select statement and it returns all the stream parsed accordingly.
My problem is that using jpa and executing the simple native query:
select B_BODY from TABLE_B where TRANSACTION_ID = 'GG-148c-01502790743907855009';
the statement doesn't return anything but querying directly the database return the record.
this is my java code:
#Transactional(readOnly = true)
public List<Object[]> retrieveBlobs(String squery) {
squery = squery + " and rownum <= "+maxResults;
Query query = em.createNativeQuery(squery);
List<Object[]> resultList = query.getResultList();
return resultList;
}
this is the sql generated:
Hibernate:
select
B_BODY
from
TABLE_B
where
TRANSACTION_ID ='GG-148c-01502790743907855009'
and rownum <= 100
i know that this way might seems weird but our team spend a lot of time trying to tokenize the stored streams(the code that identify how to parse the stream is also stored in the tables).Useless to say this application is going to be used only internally.there is a way to just execute the query as it is and retrieve the correct output?
Well, I tried to reproduce your problem on MariaDB (with mysql-connector-java + hibernate) but selecting a lob with native query was working properly.
You can try to create entities which will be holding your blob and check if this would help. Just make a standard entity with #Lob annotation over your lob column.
#Entity
#NamedQueries(
#NamedQuery(name = FIND_ALL, query = "SELECT m FROM LobEntity m")
)
public class LobEntity {
public static final String FIND_ALL = "PhpEntity.findAll";
#Id
#Column(name = "id")
private String id;
#Lob
#Column(name = "lob")
private byte[] lob;
//Use Blob class if you want to use streams.
//#Column(name = "lob")
//#Lob
//private Blob lob;
}
Given the following annotated named stored procedure query:
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(
name = "procedureName",
procedureName = "stored_procedure"
)
})
Then executing with:
StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("procedureName");
query.executeUpdate();
The stored_procedure returns postgres void.
Results in an exception: Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
.
How can this be resolved?
I resolved this by using some crutch code.
#SqlResultSetMapping(
name = "VOID_MAPPING",
classes = {
#ConstructorResult(targetClass = VoidClass.class, columns = {})
}
)
Adding the resultSetMappings to the #NamedStoredProcedureQuery.
resultSetMappings = {
"VOID_MAPPING"
}
VoidClass is simply an empty class.
public class VoidClass {}
But, I'm hoping for a better solution.