Good evening! I am trying to set values from my query to wrapper class TestWrapper
TestWrapper class:
package com.bionic.wrappers;
public class TestWrapper {
private String name;
private int duration;
public TestWrapper(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
}
Here is my query:
#NamedQuery(name = "getAvailableTestsNames",
query = "SELECT test.testName, test.duration FROM Result result JOIN result.test test JOIN result.user user where user.id = :userId"
and DAO class:
public List<TestWrapper> getAvailableTestsNames(long id){
Query query = em.createNamedQuery("getAvailableTestsNames");
query.setParameter("userId", id);
return (List<TestWrapper>)query.getResultList();
}
I get an exeption and i see that values won't set appropriate here:
public static Set<TestDTO> convertAvailableTestsToDTO(List<TestWrapper> tests){
Set<TestDTO> testDTOs = new HashSet<>();
for (TestWrapper test : tests){
TestDTO testDTO = new TestDTO(test.getName(), test.getDuration());
testDTOs.add(testDTO);
}
return testDTOs;
}
I get an expeption:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.bionic.wrappers.TestWrapper
Thank you!
I don't have enough context but in the getAvailableTestsNames meth. looks like you're doing a query that returns scalar results by returning "test.testName, test.duration" where you probably just want to return a List of TestWrapper so the query should just be " from XXX" , you can omit the select field1,field2 ... hibernate does that for you.
See section 11.4.1.3. Scalar results of https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch11.html#objectstate-querying vs. 11.4.1. Executing queries
Hope this helps
Aa.
Related
I send a Get Postman request and i am receiving status 200. The problem is that I don't get any data about it, it gives me only : [] .
Probably my error is that I don't map the constructor for the DTO class I made.
As another option I guess I have to make a projection or something similar to this, can anyone explain to me how to map the constructor and give me the data I want? I'm so messed up and dealing with this error for 2 hours and nothing.
Repository:
#Repository
public interface ManagementRepository extends JpaRepository<Management,Long>,ManagementRepositoryCustom {
#Query(value = "SELECT wm.action_description " +
"FROM testdb.warehouse_management wm " +
"WHERE wm.action_description = :action_description ", nativeQuery = true)
List<StockRecoveryDTO> findByDog(#Param("action_description") String action_description);
}
DTO:
package com.example.dto;
public class StockRecoveryDTO {
private Long id_product;
private String date;
private int quantity_product;
private String action_description;
private Long id_action;
private String quantity;
public StockRecoveryDTO() {
}
public StockRecoveryDTO(Long id_product, String date, int quantity_product, String action_description, Long id_action, String quantity) {
this.id_product = id_product;
this.date = date;
this.quantity_product = quantity_product;
this.action_description = action_description;
this.id_action = id_action;
this.quantity = quantity;
}
//GETTER SETTER
Console:
Hibernate: SELECT wm.action_description FROM testdb.warehouse_management wm WHERE wm.action_description = ?
That native query you are return only action_description so change the return type to List<String>.
I'm using EclipseLink to run some Native SQL. I need to return the data into a POJO. I followed the instructions at EclipseLink Docs, but I receive the error Missing descriptor for [Class]
The query columns have been named to match the member variables of the POJO. Do I need to do some additional mapping?
POJO:
public class AnnouncementRecipientsFlattenedDTO {
private BigDecimal announcementId;
private String recipientAddress;
private String type;
public AnnouncementRecipientsFlattenedDTO() {
super();
}
public AnnouncementRecipientsFlattenedDTO(BigDecimal announcementId, String recipientAddress, String type) {
super();
this.announcementId = announcementId;
this.recipientAddress = recipientAddress;
this.type = type;
}
... Getters/Setters
Entity Manager call:
public List<AnnouncementRecipientsFlattenedDTO> getNormalizedRecipientsForAnnouncement(int announcementId) {
Query query = em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT, AnnouncementRecipientsFlattenedDTO.class);
query.setParameter(1, announcementId);
return query.getResultList();
}
I found out you can put the results of a Native Query execution into a List of Arrays that hold Objects. Then one can iterate over the list and Array elements and build the desired Entity objects.
List<Object[]> rawResultList;
Query query =
em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT);
rawResultList = query.getResultList();
for (Object[] resultElement : rawResultList) {
AnnouncementDeliveryLog adl = new AnnouncementDeliveryLog(getAnnouncementById(announcementId), (String)resultElement[1], (String)resultElement[2], "TO_SEND");
persistAnnouncementDeliveryLog(adl);
}
You can only use native SQL queries with a class if the class is mapped. You need to define the AnnouncementRecipientsFlattenedDTO class as an #Entity.
Otherwise just create the native query with only the SQL and get an array of the data back and construct your DTO yourself using the data.
Old question but may be following solution will help someone else.
Suppose you want to return a list of columns, data type and data length for a given table in Oracle. I have written below a native sample query for this:
private static final String TABLE_COLUMNS = "select utc.COLUMN_NAME, utc.DATA_TYPE, utc.DATA_LENGTH "
+ "from user_tab_columns utc "
+ "where utc.table_name = ? "
+ "order by utc.column_name asc";
Now the requirement is to construct a list of POJO from the result of above query.
Define TableColumn entity class as below:
#Entity
public class TableColumn implements Serializable {
#Id
#Column(name = "COLUMN_NAME")
private String columnName;
#Column(name = "DATA_TYPE")
private String dataType;
#Column(name = "DATA_LENGTH")
private int dataLength;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getDataLength() {
return dataLength;
}
public void setDataLength(int dataLength) {
this.dataLength = dataLength;
}
public TableColumn(String columnName, String dataType, int dataLength) {
this.columnName = columnName;
this.dataType = dataType;
this.dataLength = dataLength;
}
public TableColumn(String columnName) {
this.columnName = columnName;
}
public TableColumn() {
}
#Override
public int hashCode() {
int hash = 0;
hash += (columnName != null ? columnName.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof TableColumn)) {
return false;
}
TableColumn other = (TableColumn) object;
if ((this.columnName == null && other.columnName != null) || (this.columnName != null && !this.columnName.equals(other.columnName))) {
return false;
}
return true;
}
#Override
public String toString() {
return getColumnName();
}
}
Now we are ready to construct a list of POJO. Use the sample code below to construct get your result as List of POJOs.
public List<TableColumn> findTableColumns(String table) {
List<TableColumn> listTables = new ArrayList<>();
EntityManager em = emf.createEntityManager();
Query q = em.createNativeQuery(TABLE_COLUMNS, TableColumn.class).setParameter(1, table);
listTables = q.getResultList();
em.close();
return listTables;
}
Also, don't forget to add in your POJO class in persistence.xml! It can be easy to overlook if you are used to your IDE managing that file for you.
Had the same kind of problem where I wanted to return a List of POJOs, and really just POJOs (call it DTO if you want) and not #Entity annotated Objects.
class PojoExample {
String name;
#Enumerated(EnumType.STRING)
SomeEnum type;
public PojoExample(String name, SomeEnum type) {
this.name = name;
this.type = type;
}
}
With the following Query:
String query = "SELECT b.name, a.newtype as type FROM tablea a, tableb b where a.tableb_id = b_id";
Query query = getEntityManager().createNativeQuery(query, "PojoExample");
#SuppressWarnings("unchecked")
List<PojoExample> data = query.getResultList();
Creates the PojoExample from the database without the need for an Entity annotation on PojoExample. You can find the method call in the Oracle Docs here.
edit:
As it turns out you have to use #SqlResultSetMapping for this to work, otherwise your query.getResultList() returns a List of Object.
#SqlResultSetMapping(name = "PojoExample",
classes = #ConstructorResult(columns = {
#ColumnResult(name = "name", type = String.class),
#ColumnResult(name = "type", type = String.class)
},
targetClass = PojoExample.class)
)
Just put this anywhere under your #Entity annotation (so in this example either in tablea or tableb because PojoExample has no #Entity annotation)
Here is the problem I am currently having. My DAO class returns data in index but I want to return the selected data to client in JSON format. How can I do it?
The controller class which returns data in json format.
MyController.java
#RequestMapping(value = "/ohlc",method = RequestMethod.POST)
public #ResponseBody List<OhlcResponse> getOhlc(#RequestBody OhlcRequest ohlcRequest) {
List<OhlcResponse> ohlc = ohlcService.getOhlc(ohlcRequest);
return ohlc;
}
Dao class returns 4 datas (minprice, maxprice, closingprice and previousclosingprice) by executing stored procedure.
OhlcDaoImpl.java
public List<OhlcResponse> getOhlc(OhlcRequest ohlcRequest) {
session = sessionFactory.openSession();
SQLQuery q = session.createSQLQuery("EXEC uspGetOhlc :StockCode, :fromDate, :toDate");
q.setString("StockCode",ohlcRequest.getStockSymbol());
q.setDate("fromDate",ohlcRequest.getFromDate());
q.setDate("toDate", ohlcRequest.getToDate());
List<OhlcResponse> l = q.list();
return l;
}
My stored procedure
USE WealthFeedSrv
GO
CREATE PROCEDURE uspGetOhlc
#StockCode varchar(50),
#fromDate date,
#toDate date
AS
BEGIN
SELECT spd.ClosingPrice, spd.PreviousClosingPrice, spd.MinPrice, spd.MaxPrice
FROM StockPriceDetl spd
inner join Stock stk on stk.Id = spd.StockId
inner join StockPriceMast spm on spm.Id = spd.MastId
WHERE stk.StockSymbol= #StockCode AND spm.TranDate Between #fromDate and #toDate
END
GO
The pojo class I want returned data to bind.
OhlcResponse.java
public class OhlcResponse {
private BigDecimal MaxPrice;
private BigDecimal MinPrice;
private BigDecimal PreviousClosingPrice;
private BigDecimal ClosingPrice;
public BigDecimal getMaxPrice() {
return MaxPrice;
}
public void setMaxPrice(BigDecimal maxPrice) {
MaxPrice = maxPrice;
}
public BigDecimal getMinPrice() {
return MinPrice;
}
public void setMinPrice(BigDecimal minPrice) {
MinPrice = minPrice;
}
public BigDecimal getPreviousClosingPrice() {
return PreviousClosingPrice;
}
public void setPreviousClosingPrice(BigDecimal previousClosingPrice) {
PreviousClosingPrice = previousClosingPrice;
}
public BigDecimal getClosingPrice() {
return ClosingPrice;
}
public void setClosingPrice(BigDecimal closingPrice) {
ClosingPrice = closingPrice;
}
public OhlcResponse(){
}
}
The result i want
"maxPrice":"200",
"minPrice":"300",
"ClosingPrice":"400",
"PreviousClosingPrice":"500"
The error says cannot cast to OhlcResponse. How can I bind the object returned by OhlcDao into OhlcResponse class and return JSON Format?
I am using Apache Commons DBUtils according to QueryRunner#insert method in its documentation,insert return the generic type of ResultSetHandler. I have a BR_Author object at my project.
BR_Author.java
import org.springframework.stereotype.Repository;
#Repository
public class BR_Author {
private int id;
private String authorName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
}
I write a simple insert statement at my service class like
AuthorService#createAuthor
public BR_Author createAuthor(String authorName) throws ApiException {
String sql = "Insert into BR_AUTHOR(authorName) VALUES(?)";
ResultSetHandler<BR_Author> rs = new BeanHandler<BR_Author>(
BR_Author.class);
QueryRunner qr = new QueryRunner(dataSource);
Object[] params = { authorName };
try {
BR_Author author = qr.insert(sql, rs, params);
System.out.println("Br_Author:" + author);
return author;
} catch (SQLException e) {
throw new ApiException(ErrorCode.ERR20001, e.getMessage());
}
}
I am trying to return the added value at createAuthor method, but if i configure id field as auto increment object return as
Br_Author:Br_Author [id=0, authorName=null]
when i check the db i see that it adds the values successfully.
If i disable auto increment and set id from code, author object is null. So i want to learn that am i misunderstand QueryRunner#insert method or it has a bug. I already check below links.
QueryRunner_insert_add_javadoc.patch
Generated key handling for updates
BTW: Select queries working fine for BR_Author class so it means there shouldn't be any mapping issue.
I didn't find any official solution from DBUtils API so i just return generated ID and then query it after insert the record with this id at Service layer. This way method return Object at service layer, but i do one extra query.
I have a query. But it does not work. I tested it on Oracle SQL Developer, It worked. So I wrote it in namedquery.
The query is below that works fine on Oracle SQL Developer
SELECT q.* FROM TAKE_EXAM_QUESTION q
INNER JOIN TAKE_EXAM e
on q.tk_exam_id = e.tk_exam_id
where e.user_id= :userId;
And I typed above query in Entity class
#NamedQuery(name = "TakeExamQuestionEntity.question", query = "SELECT qs FROM TakeExamQuestionEntity qs INNER JOIN TakeExamEntity ex on qs.tk_exam_id = ex.tk_exam_id where ex.user_id= :userId "),
But it is not working, I do not know why now working please suggest me.
If you generate entity from table, any fields of table will be remove _ and first character after _ will be upper case. Thus, you should write NamedQuery as below example.
#NamedQuery(name = "TakeExamQuestionEntity.question",
query = "SELECT qs FROM TakeExamQuestionEntity qs
INNER JOIN TakeExamEntity ex on qs.tkExamId = ex.tkExamId
where ex.userId= :userId ")
If it not work, you should check you entity they are separated to 2 class (entity Primary Key and entity class) or not.
#Embeddable
public class EmployeePK implements Serializable {
private String name;
private long id;
public EmployeePK() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int hashCode() {
return (int) name.hashCode() + id;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof EmployeePK)) return false;
if (obj == null) return false;
EmployeePK pk = (EmployeePK) obj;
return pk.id == id && pk.name.equals(name);
}
}
#Entity
public class Employee implements Serializable {
EmployeePK primaryKey;
public Employee() {
}
#EmbeddedId
public EmployeePK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(EmployeePK pk) {
primaryKey = pk;
}
...
}
If your entity has generated as 2 class as above example.
You should define
SELECT e FROM Employee e
where e.primaryKey.name=:name
the primaryKey will be an object of EmployeePK that has annotation Embeddable.
If you want to use native query you should use #NamedNativeQuery instead of #NamedQuery.
See also: NamedNativeQuery