Hibernate many to one eager fetching not working

2019-09-18 13:26发布

I am trying to fetch data from database using hibernate annotation but it is not working as my expected. I have a two table Employee and Department. the java code is as below :

Employee class

 @Entity
    @Table(name = "EMPLOYEE")        
    public class EmployeeBO {

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name = "EMPID")
        private int empId;
        @Column(name = "EMPNAME")
        private String empName;
        @Column(name = "SALARY")
        private int empSalary;
        @Column(name = "EMPADDRESS")
        private String empAddress;
        @Column(name = "EMPAGE")
        private int empAge;
        @Column(name = "DEPTID")
        private Integer deptId; 
        @ManyToOne(fetch=FetchType.EAGER)
        @JoinColumn(name="DEPTID", nullable = true, insertable = false, updatable = false)
        private DepartmentBO departmentBO;
// getter and setter 
    }

Department class :

@Entity
@Table(name = "DEPARTMENT")
public class DepartmentBO {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "DEPTID")
    private int deptid;

    @Column(name = "DEPTNAME")
    private String deptName;
   // getter and setter.
}

spring-servlet.xml file :

<?xml version="1.0" encoding="UTF-8"?>
<!--?xml  version="1.0" encoding="UTF-8"?-->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


    <context:annotation-config></context:annotation-config>

    <context:component-scan base-package="com.web"></context:component-scan>

    <context:property-placeholder location="file:D:/EasyProp/db.properties" ignore-unresolvable="false"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="prefix" value="/WEB-INF/jsp/" />  
        <property name="suffix" value=".jsp" />  
    </bean>

    <bean id="basicDataSource" 
         class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 

        <property name="driverClassName" value="${driver.classname}" />
        <property name="url" value="${driver.url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
<!--        <property name="initialSize" value="10"/> -->
<!--         <property name="maxActive"  value="25"/> -->
<!--         <property name="maxIdle" value="25"/>   -->
        <!-- <aop:scoped-proxy/> -->
    </bean> 
    <tx:annotation-driven />
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>

    <!-- <bean id="dbUtil" class="com.web.utility.OnLoadStartUp" init-method="initialize">
        <property name="dataSource" ref="basicDataSource" />
    </bean> -->

    <!-- <bean id="loadOnStartUp" class="com.web.utility.LoadOnStartUp">
        <property name="baseService" ref="baseService"></property>
    </bean> -->

    <bean id="mySessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="basicDataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.web.bo.EmployeeBO</value>
                <value>com.web.bo.DepartmentBO</value>  
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hmb2ddl.auto">validate</prop>
                <prop key="hibernate.generate_statistics">true</prop>
                <prop key="hibernate.jdbc.fetch_size">10</prop>
                <prop key="hibernate.jdbc.batch_size">25</prop>
                <prop key="hibernate.jdbc.batch_versioned_data">true</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.default_batch_fetch_size">8</prop>
                <prop key="hibernate.order_updates">true</prop>
                <prop key="hibernate.connection.release_mode">on_close</prop>
                <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
                <prop key="hibernate.bytecode.provider">javassist</prop>                
            </props>
        </property>
    </bean>
</beans>

when i trying to fetch all data from employee and department table but it only returns the data from employee table my code for hit hql query as below :

List<EmployeeBO> empList = null; 
        empList = sessionFactory.getCurrentSession().createQuery("From "+employeeBO.getClass().getName()).list();   

above query is hit as below on database.

select employeebo0_.EMPID as EMPID0_, employeebo0_.DEPTID as DEPTID0_, employeebo0_.EMPADDRESS as EMPADDRESS0_, employeebo0_.EMPAGE as EMPAGE0_, employeebo0_.EMPNAME as EMPNAME0_, employeebo0_.SALARY as SALARY0_ from EMPLOYEE employeebo0_

But i want all data of the employee table and department table using Eager fetching.

4条回答
混吃等死
2楼-- · 2019-09-18 14:02

I think you have missed the anotation for lazy loading.

You have to use (fetch=FetchType.LAZY) on a association which you want to lazy load

查看更多
甜甜的少女心
3楼-- · 2019-09-18 14:04

It works as expected. The EmployeeBO contains a DepartmentBO. The DepartmentBO will automatically be filled the moment you access it.

This is not true, if the Hibernate session containing the EmployeeBO has ended. Then the EmployeeBO is transient and hibernate will not fetch the missing object.

To enforce filling the DepartmentBO, you can add a fetch clause to your hql code. But that is not lazy fetching any more.

The HQL

from EmployeeBO join fetch EmployeeBO.department 

should do the job (replace the EmployeeBO with the actual entity name).

See here in the hibernate docs: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html and for the fetching strategies here https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-fetching

From the comments, you actually want eager fetching on the relationship, so you need to declare the fetchtype to be eager:

@ManyToOne(fetch=FetchType.EAGER)

should fix it. Adding another doc here: https://docs.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html

查看更多
放荡不羁爱自由
4楼-- · 2019-09-18 14:06

Hibernate by default has Lazy loading. i.e. it would not fetch the data of another table. In you case if you want the data of department table, you will have to call getter of departmentBO if you are in hibernate session. Note: it will fire another query. else you can also use

Hibernate.initialize(entity.getdepartmentBO())

If you want by default to get the department data. use the following code

@ManyToOne(fetch=FetchType.EAGER)
查看更多
男人必须洒脱
5楼-- · 2019-09-18 14:24

There are two ways to do this: 1) use EAGER fetch type 2) call getDepartmentBO() on each employee after you get the employee

查看更多
登录 后发表回答