1
votes

It's a ORM application which uses Spring 5 & Hibernate 5
I'm using Hibernate Callback interface in DAO layer to get the record of the employees in between specific id's. I have used named parameter :min & :max. Though it's successfully generating the query but in service layer it's throwing an exception.
I'm unable to get the root cause of that exception

DAOIMPL
------------

private static final String get_Records_By_Range="SELECT id,name,company,address,salary FROM EmployeeHLO where id>=:min and id<=:max";

@SuppressWarnings("unchecked")
    @Override
    public List<EmployeeHLO> getRecordsByIdRange(int start, int end) throws Exception {
        List<EmployeeHLO> listHlo= null;


        listHlo=  ht.execute(new HibernateCallback<List<EmployeeHLO>>() {
            @Override
            public List<EmployeeHLO> doInHibernate(Session ses) throws HibernateException {
                Query query= null;

                query= ses.createQuery(get_Records_By_Range);
                query.setInteger("min", start);
                query.setInteger("max", end);

                List<EmployeeHLO> listHloo= query.list();
                return listHloo;
            }

        });
        return listHlo


ServiceIMPL
-------------------

@Override
    public List<EmployeeDto> getRecordsByRange(int start, int end) throws Exception {
        List<EmployeeHLO> listHlo= null;
        List<EmployeeDto> listDto= new ArrayList<EmployeeDto>();

        //get records from dao
        listHlo= dao.getRecordsByIdRange(start, end);

        //copy hlo to dto

        listHlo.forEach(hlo->{   //getting error in this line
            EmployeeDto dto= new EmployeeDto();
            BeanUtils.copyProperties(hlo, dto);
            listDto.add(dto);
        });
        return listDto;
    }

Test
----------

try {

            //get record by range
            listDto= service.getRecordsByRange(1, 5);
            listDto.forEach(rangeDto->{
                System.out.println(rangeDto.getId()+" "+rangeDto.getName()+" "+rangeDto.getCompany()+" "+rangeDto.getAddress()+" "+rangeDto.getSalary());
            });


Domain(EMployeeHLO) && EmployeeDTo also contains the same property
----------------------

import java.io.Serializable;

public class EmployeeHLO implements Serializable {
    private int id;
    private String name;
    private String company;
    private String address;
    private float salary;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public float getSalary() {
        return salary;
    }
    public void setSalary(float salary) {
        this.salary = salary;
    }

}


Error
-----------

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.st.domain.EmployeeHLO
    at java.util.ArrayList.forEach(Unknown Source)
    at com.st.service.EmployeeServiceImpl.getRecordsByRange(EmployeeServiceImpl.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:338)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:197)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy31.getRecordsByRange(Unknown Source)
    at com.st.test.Test.main(Test.java:46)


EmployeeHLO.hbm.xml
------------------------

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.st.domain.EmployeeHLO" table="orm_table">
        <id name="id" column="id" length="10" type="int">
            <generator class="increment"></generator>
        </id>

        <property name="name" column="name" type="string" not-null="true" length="50"></property>
        <property name="company" column="company" type="string" not-null="true" length="50"></property>
        <property name="address" column="address" type="string" not-null="true" length="50"></property>
        <property name="salary" column="salary" type="float" precision="2" not-null="true" length="10"></property>
    </class>

    <query name="HQL_GET_RECORDS_BY_RANGE">
   <![CDATA[
     from EmployeeHLO where id>=:min and id<=:max
   ]]>
   </query>
</hibernate-mapping>
1

1 Answers

2
votes

You have to select the entity and not all it's field or hibernate will return a list of those fields e.g. A list of Object[] since there are multiple types.

Try to change it to:

"SELECT emp FROM EmployeeHLO emp where emp.id>=:min and emp.id<=:max"

The emp is an alias of the table EmployeeHLO that we can then use in the query for simplicity.

When you refer to a field of the entity it's a good practice to point to the entity where emp.id instead of where id since you could virtually select from multiple tables or join them.

In the select clause, if you want returned the entity instead of other construct (e.g. It's always a List<Object[]>) representing your selected fields, you have to select the whole table by alias.

This way hibernate does his magic and return you an instance of the entity for each row with the field already filled with the row values