nested exception is org.hibernate.HibernateException: Could not instantiate resultclass - spring

what is wrong ?
public List < ReportDTO> listProductAll() {
String sql
= "select "
+ "ip.product_name as productName, "
+ "ip.base_price as basePrice, "
+ "iu.username as username "
+ "from tb_buy a "
+ "left join in_product ip on a.id_product = ip.product_id "
+ "left join im_users iu on a.id_user = iu.user_id ";
Query q = identifyServer.getCurrentSession().createSQLQuery(sql)
.addScalar("productName")
.addScalar("basePrice")
.addScalar("username")
.setResultTransformer(Transformers.aliasToBean(ReportDTO.class));
return q.list();
}
public class ReportDTO {
private String productName;
private Double basePrice;
private String username;
public ReportDTO(String productName, Double basePrice, String username) {
this.productName = productName;
this.basePrice = basePrice;
this.username = username;
}
// getter setter
org.springframework.orm.jpa.JpaSystemException: Could not instantiate resultclass: ReportDTO; nested exception is org.hibernate.HibernateException: Could not instantiate resultclass: ReportDTO
solve
public ReportDTO() {}

Hibernate requires all entities to have a default no args constructor.
If your entity class doesn't have it, or if it's not public, you'll get this exception.

Related

Spring data projection for native query not mapped to interface

This my repostoriy for retrieve items
#Query(value = "SELECT DISTINCT M.ID as \"id\", "
+ " M.NAME_PRIMARY_LANG as \"name\" "
+ " FROM ECOMMERCE_CORE.MERCHANT_ITEMS M , "
+ " ECOMMERCE_CORE.PRODUCT_UNIT_OF_MEASURE P , "
+ " ECOMMERCE_CORE.LOOKUP_TYPES_STATUS S , "
+ " ECOMMERCE_CORE.ITEM_TYPES T , "
+ " ECOMMERCE_CORE.ITEM_PRICE I,"
+ " ECOMMERCE_CORE.MERCHANT_ITEM_BRAND B, "
+ " ECOMMERCE_CORE.MERCHANT_ITEM_CATEGORY C "
+ " WHERE M.ID = P.PRODUCT_ID AND M.ID=I.PRODUCT_ID AND M.ID = B.MERCHANT_ITEM_ID AND S.ID=M.STATUS_ID AND M.TYPE = T.ID AND M.MERCHANT_ID =?1 AND M.STATUS_ID =?2 "
+ " AND P.BRANCH_ID = ?3 AND I.CHANNEL_ID = ?4 ",
nativeQuery = true
)
List<ItemModelProjection> findBySupplierIdAndStatusCode(long id, long status, long branchId, long channelId, Pageable pageable);
and this my interface which i need to map the result to it
#Getter
#EqualsAndHashCode(of = {"id"})
public class ItemModelProjection {
private String id;
private String name;
public ItemModelProjection(final String id, final String name) {
this.id = id;
this.name = name;
}}
and the result of this query not mapped to the interface , what is the problem for it ?
You can solve this issue and achieve the result by using projections by making your DTO an interface with getters for columns returned by the query.
All you need to do is to have interface and contain query domains starting with get.
public interface ItemModelProjection {
Long getId();
String getName();
}
You need an interface if you want to retrieve those values. And be careful with the naming of the methods. If you have like in your case AS name then call the method getName(). But if you don't have AS specified and you are returning a value for example like PRODUCT_UNIT_OF_MEASURE then use the following method name: getProduct_Unit_Of_Measure().
For getting those two values use the following interface:
public interface ItemModelProjection {
String getId();
String getName();
}

HQL with parameters giving error IllegalArgumentException

I am getting an exception while trying to fetch some data using HQL with parameters. Below is the exception and the code.
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: TESTDB.ORDER_DETAILS is not mapped [SELECT DATE,ORDER_NAME,DESCRIPTION FROM TESTDB.ORDER_DETAILS WHERE ORDER_ID = :orderId ORDER BY DATE DESC]
//*************************************************************
OrderDetailDTO orderDetailDTO = new OrderDetailDTO();
List<OrderDetailDTO> orderList = new ArrayList<OrderDetailDTO>();
ResultSet rs = null;
String queryStr = "SELECT DATE,ORDER_NAME,DESCRIPTION "
+ "FROM TESTDB.ORDER_DETAILS WHERE ORDER_ID = :orderId "
+ "ORDER BY DATE DESC";
org.hibernate.query.Query query = session.createQuery(queryStr).setParameter("orderId", ordId);
rs = (ResultSet)query.getResultList();
while(rs.next()!=false){
orderDetailDTO.setOrderName(rs.getString("ORDER_NAME"));
orderDetailDTO.setDescription(rs.getString("DESCRIPTION"));
orderDetailDTO.setDate(rs.getTimestamp("DATE"));
orderList.add(orderDetailDTO);
}
//*************************************************************
//ordId : This one I have as argument in the method
I have to use this parameterised HQL to avoid SQL injection. Can anyone figure out why the weird error of IllegalArgumentException is comming.
The solution is done by using the entity names instead of the database table names. There is the catch. In JPQL we need to use the java bean class name in the query. When I replaced the java bean class name with the java bean fields name everything worked fine.
Also in JPQL mentioning the schema name is not required as in case of JPQL hibernate will use the schema
as defined by the hibernate.default_schema configuration property. The URL used for reference is https://vladmihalcea.com/how-to-resolve-the-hibernate-global-database-schema-and-catalog-for-native-sql-queries/
Below is the working code :
The java code for the database table :
package demo.jpql;
import java.io.Serializable;
import javax.persistence.*;
import java.sql.Timestamp;
#Entity
#Table( name = "ORDER_DETAILS" )
public class OrderDetails implements Serializable {
private static final long serialVersionUID = 1L;
#Column( name = "ORDER_NAME", length = 50 )
private String orderName;
#Column( name = "DESCRIPTION", length = 50 )
private String desc;
#Column( name = "DATE" )
private Timestamp date;
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Timestamp getDate() {
return date;
}
public void setDate(Timestamp date) {
this.date = date;
}
}
//*************************************************************
OrderDetailDTO orderDetailDTO = new OrderDetailDTO();
List<OrderDetailDTO> orderList = new ArrayList<OrderDetailDTO>();
ResultSet rs = null;
String queryStr = "SELECT date,orderName,desc"
+ "FROM OrderDetails WHERE orderID =:orderId "
+ "ORDER BY date DESC";
org.hibernate.query.Query query =
session.createQuery(queryStr).setParameter("orderId", ordId);
List<Object> rsltLstOrderDtls = (List<Object>)query.getResultList();
Iterator<Object> itr = rsltLstOrderDtls.iterator();
while (itr.hasNext()) {
Object[] obj = (Object[]) itr.next();
orderDetailDTO.setOrderName(String.valueOf(obj[1]));
orderDetailDTO.setDescription(String.valueOf(obj[2]));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
java.util.Date parsedDate = dateFormat.parse(String.valueOf(obj[0]));
Timestamp timestamp = new java.sql.Timestamp(parsedDate.getTime());
orderDetailDTO.setDate(timestamp);
orderList.add(orderDetailDTO);
}
//*************************************************************

Conversion type error with native JPA query

I wrote a native query to get the top 5 tags for questions, I created a class to hold the returned data - which is only the tag name and the total number of occurrences, but I get a type conversion error that I don't understand.
#Query(value = "select distinct t.naam as name, count(t.id) as total from vragen_tags vt " +
"left join tags t on vt.tag_id = t.id " +
"left join vragen v on vt.vraag_id = v.id " +
"where v.actief = true " +
"group by t.naam " +
"order by total desc " +
"limit ?1", nativeQuery = true)
Set<TagAndCountResponse> getTopTags(int limit);
Class:
public class TagAndCountResponse {
private String name;
private int total;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
But I get this error:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [be.ambrassade.jeugdlink.model.response.TagAndCountResponse]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
...
What is causing this error?
I found the answer through another medium. (kudos to Les) The solution is to use projections (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections), so in my case rewriting the concrete class to this interface makes it work.
public interface TagAndCountResponse {
String getName();
int getTotal();
}

i get "path expected for join" and Query exception: unable to resolve path [Product.ProductID]

I have two models:
#Entity
public class Product{
#Id
private String ProductID;
private String ProductName;
#ManyToOne
#JoinColumn
private Supplier supplier;
private int quantity;
private int price;
//getter setter...
//constructor...
}
#Entity
public class Supplier {
#Id
private String SupplierID;
private String SupplierName;
private String Phone;
private String Address;
private String Email;
//getter setter
//constructor
}
In jdbc template of spring i can get all record i want like this:
public List<Product> getProducts(int take, int skip){
List<Product> list = new ArrayList<Product>();
String sql = "SELECT product.ProductID, product.ProductName, product.Quantity, supplier.SupplierID"
+ ", supplier.SupplierName, product.Price"
+ " FROM product INNER JOIN supplier ON product.SupplierID = supplier.SupplierID"
+ " LIMIT " + skip + "," + take + "";
list = jdbcTemplate.query(sql, new ProductMapper());
return list;
public class ProductMapper implements RowMapper<Product> {
public Product mapRow(ResultSet rs, int line) throws SQLException {
Product product = new Product();
product.setProductID(rs.getString("ProductID"));
product.setProductName(rs.getString("ProductName"));
product.setQuantity(rs.getInt("Quantity"));
product.setSupplier(new Supplier(rs.getString("SupplierID"), rs.getString("SupplierName")));
product.setPrice(rs.getInt("Price"));
return product;
}
But it's wrong in hibernate:
//--------hibernate-------
Session session = sessionFactory.openSession();
session.beginTransaction();
String queryStr = "SELECT Product.ProductID, Product.ProductName, Product.Quantity, Supplier.SupplierID"
+ ", Supplier.SupplierName, Product.Price"
+ " FROM Product INNER JOIN Supplier ON Product.SupplierID = Supplier.SupplierID";
List<Product> list = new ArrayList<Product>();
try {
Query query = session.createQuery(queryStr);
query.setFirstResult(skip);
query.setMaxResults(take);
list = (List<Product>) query.list();
session.getTransaction().commit();
}
catch(Exception e) {
System.out.println("Exception e" + e);
session.getTransaction().rollback();
}
finally {
session.close();
}
return list;
}
i get "path expected for join" and Exception eorg.hibernate.QueryException: Unable to resolve path [Product.ProductID], unexpected token [Product] [SELECT Product.ProductID .... ]
Anyone can help me to get the same result when i do with jdbc template.
SELECT p.ProductID, p.ProductName, p.Quantity, s.SupplierID, s.SupplierName, p.Price
FROM Product p
INNER JOIN p.Supplier s
You need to use paths in your HQL query, from one entity to the other. The Hibernate documentation on HQL and joins provides more information here.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-joins
String sql = "SELECT product.ProductID, product.ProductName,
product.Quantity, supplier.SupplierID"
+ ", supplier.SupplierName, product.Price"
+ " FROM product INNER JOIN supplier ON product.SupplierID = supplier.SupplierID"
+ " LIMIT " + skip + "," + take + "";
If you are using sql query then you need to give SQL table and sql table columns,
But here you are mixing SQL table and Java Classes , like
product is probably a SQL table and Product is the entity class.
So change your query as
String sql = "SELECT p.ProductID, p.ProductName, p.Quantity, s.SupplierID"
+ ", s.SupplierName, s.Price"
+ " FROM Product p INNER JOIN Supplier s ON p.SupplierID = s.SupplierID"
+ " LIMIT " + skip + "," + take + "";
Also, your variable names are not in camelCase, this can mess up Hibernate's way of mapping a Entity property to table columns, so pay special attention to getter and setters .

Hibernate not retrieving correct value with SELECT and ORA-00984: column not allowed here error

I am facing two issues here :
Issue 1) I am trying to get the COMPANY_ID using the selectCompanyID variable as shown below. I am storing the value returned into getCompanyID variable.When I tried to print it, as shown in the console output below, it's always printing number 1. However, when I tried to run the actual SQL in the
Oracle SQL developer SQL Worksheeet, I got different number. Because of this I could insert wrong ID in the following INSERT statement where it's
getting used.
Issue 2) As shown in the SQL, I am also getting ORA-00984: column not allowed here error. Noticed, people encountering similar error in the following post :
"column not allowed here" error in INSERT statement
But here I don't have straightforward SQL INSERT statement as the one mentioned in the above post with missing quotes.
public boolean insertEmployeeDetails(Employee employee)
{
logger.debug("Starting EmployeeDaoImpl.insert() .....");
Session session = null;
Transaction tx = null;
boolean status = true;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
//The following SELECT query returns a number when I ran it in the Oracle SQL developer SQL worksheet
String selectCompanyID = "SELECT"
+ " VALUE_EMP_ID"
+" FROM "
+ " COMPANY_DATA"
+" WHERE"
+ " testing_id = 1234"
+" AND "
+ " company_employee_id = 3345";
int getCompanyID = session.createSQLQuery(selectCompanyID)
.executeUpdate();
System.out.println("GetCompanyID Test below");
System.out.println(getCompanyID);
String hqlInsert = "INSERT INTO Employee (NAME, IS_CORRECT,IS_WRONG,COMPANY_ID, TRANSACTION_ID,DEFINITION) VALUES"
+ "( SELECT value_emp_id FROM COMPANY_DATA WHERE testing_id = 1234 AND"
+ " company_employee_id = 3345))";
String hqlInsert = "INSERT INTO Employee (NAME,IS_CORRECT,IS_WRONG,COMPANY_ID,TRANSACTION_ID,DEFINITION) VALUES "
+ "("
+employee.getName()+","
+employee.getIsCorrect()+","
+employee.getIsWrong()+","
+getCompanyID+","
+employee.getTransactionId()+","
+employee.getDefinition()+")";
System.out.println("October 3 Checking for hqlInsert");
System.out.println(hqlInsert);
int createdEntities = session.createSQLQuery( hqlInsert )
.executeUpdate();
session.persist(employee);
tx.commit();
System.out.println("October 3 BELOW Checking for hqlInsert");
System.out.println(hqlInsert);
System.out.println("Checking for CreatedEntities");
System.out.println(createdEntities);
} catch(Exception ex) {
tx.rollback();
ex.printStackTrace();
status = false;
} finally {
session.close();
}
logger.debug("Completed EmployeeDaoImpl.insert() .....");
return status;
}
Console :
Hibernate:
SELECT
VALUE_EMP_ID
FROM
COMPANY_DATA
WHERE
testing_id = 1234
AND company_employee_id = 3345
GetCompanyID Test below
1
October 3 Checking for hqlInsert
INSERT INTO Employee (NAME,IS_CORRECT,IS_WRONG,COMPANY_ID,TRANSACTION_ID,DEFINITION) VALUES (Terminology,0,0,1,0,definitionTest)
Hibernate:
INSERT
INTO
Employee
(NAME,IS_CORRECT,IS_WRONG,COMPANY_ID,TRANSACTION_ID,DEFINITION)
VALUES
(Terminology,0,0,1,0,definitionTest)
2017-10-03 11:32:43.753 WARN 5392 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 984, SQLState: 42000
2017-10-03 11:32:43.753 ERROR 5392 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : ORA-00984: column not allowed here
Here is my Entity Class Employee.java is as follows:
package abc.def.mypackage.orm
#Entity
#Table(name = "EMPLOYEE")
public class Employee {
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIsCorrect() {
return isCorrect;
}
public void setIsCorrect(int isCorrect) {
this.isCorrect = isCorrect;
}
public int getIsWrong() {
return isWrong;
}
public void setIsWrong(int isWrong) {
this.isWrong = isWrong;
}
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
public Integer getTransactionId() {
return transactionId;
}
public void setTransactionId(Integer transactionId) {
this.transactionId = transactionId;
}
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
#Id
#Column(name = "EMPLOYEE_ID")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seqgen")
#SequenceGenerator(name = "seqgen", sequenceName = "EMPLOYEE_AUTOINC_SEQ")
private int employeeId;
#Column(name = "NAME")
private String name;
#Column(name = "DEFINITION")
private String definition;
#Column(name = "IS_CORRECT")
private int isCorrect;
#Column(name = "IS_WRONG")
private int isWrong;
#Column(name = "COMPANY_ID")
private int companyId;
#Column(name = "TRANSACTION_ID", nullable = true)
private Integer transactionId;
}
Try putting your String values employee.getName() and employee.getDefinition() in your insert statement into quotes '
String hqlInsert = "INSERT INTO Employee (NAME,IS_CORRECT,IS_WRONG,COMPANY_ID,TRANSACTION_ID,DEFINITION) VALUES "
+ "('"
+employee.getName()+"',"
+employee.getIsCorrect()+","
+employee.getIsWrong()+","
+getCompanyID+","
+employee.getTransactionId()+",'"
+employee.getDefinition()+"')";

Resources