使用spring数据进行延迟加载 - 集合与任何会话无关

时间:2015-01-05 05:15:43

标签: java spring-mvc jpa spring-data-jpa

我有一个约有20个jpa实体的小项目;这一切都是关于插入和检索数据。 spring数据对我来说是一个不错的解决方案,但现在我对LazyLoading有一个停止的问题。

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    metadata-complete="true"
    version="2.5">

    <description>Multi vendor</description>

    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>webapp.root.springwebbasic</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/SpringApplicationContext.xml</param-value>
    </context-param>

    <context-param>
        <param-name>defaultHtmlEscape</param-name>
        <param-value>true</param-value>
    </context-param>


    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>




    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/SpringWebConfig.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file></welcome-file>
    </welcome-file-list>

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <page-encoding>UTF-8</page-encoding>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>
        </jsp-property-group>
    </jsp-config>

<filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>


   <filter>    
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>    
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>    
        <init-param>    
            <param-name>entityManagerFactoryBeanName</param-name>    
            <param-value>entityManagerFactory</param-value>    
        </init-param>   
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
    <init-param>
        <param-name>flushMode</param-name>
        <param-value>AUTO</param-value>
    </init-param>  
    </filter>    

    <filter-mapping>    
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>    
        <url-pattern>/*</url-pattern>    
    </filter-mapping>   

</web-app>

springWebconfig.xml

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

    <context:component-scan base-package="com.mao" />
    <mvc:annotation-driven />
    <mvc:resources mapping="/resources/**" location="/resources/" cache-period="3600" />
    <mvc:default-servlet-handler />

</beans>

ApplicationContext.java,它是数据访问的java配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="com.mao.services")
public class ApplicationContext {


    private static final String PROPERTY_NAME_DATABASE_DRIVER = "com.mysql.jdbc.Driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "ffs";
    private static final String PROPERTY_NAME_DATABASE_URL = " jdbc:mysql://localhost:3306/myfdfd";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "fdfd";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "org.hibernate.dialect.MySQL5InnoDBDialect";
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "true";
    private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = "org.hibernate.cfg.ImprovedNamingStrategy";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "true";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "com.mao.entites";



    @Bean
    public DataSource dataSource() {
        BoneCPDataSource dataSource = new BoneCPDataSource();

        dataSource.setDriverClass(PROPERTY_NAME_DATABASE_DRIVER);
        dataSource.setJdbcUrl(PROPERTY_NAME_DATABASE_URL);
        dataSource.setUsername(PROPERTY_NAME_DATABASE_USERNAME);
        dataSource.setPassword(PROPERTY_NAME_DATABASE_PASSWORD);

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() throws ClassNotFoundException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN);
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);

        Properties jpaProterties = new Properties();

        jpaProterties.put("hibernate.dialect", PROPERTY_NAME_HIBERNATE_DIALECT);
        jpaProterties.put("hibernate.format_sql", PROPERTY_NAME_HIBERNATE_FORMAT_SQL);
        jpaProterties.put("hibernate.ejb.naming_strategy", PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY);
        jpaProterties.put("hibernate.show_sql", PROPERTY_NAME_HIBERNATE_SHOW_SQL);

        entityManagerFactoryBean.setJpaProperties(jpaProterties);
        return entityManagerFactoryBean;
    }

}

我有这样的知识库

public interface  VendorRepository  extends JpaRepository<Vendor, Long> {

}

当我尝试获取延迟集合时,问题出现在控制器中

@Controller
@RequestMapping("/analysis")
public class Analysis {
@Resource
private VendorRepository vendorRepository;
@RequestMapping(value = "/vendors", method = RequestMethod.GET)
@ResponseBody
public String getVendors()
{
    List<Vendor> vendorList= vendorRepository.findAll();
    Hibernate.initialize(vendorList.get(0).getVedorTechnologies()); 
    return vendorList.get(0).getVedorTechnologies().get(0).getName();
}

实体类

@Entity
@NamedQuery(name="Vendor.findAll", query="SELECT v FROM Vendor v")
public class Vendor implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="vendor_id")
    private int vendorId;

    @Column(name="vendor_name")
    private String vendorName;

    //bi-directional many-to-one association to VedorTechnology
    @OneToMany(mappedBy="vendor")
    private List<VedorTechnology> vedorTechnologies;

    public Vendor() {
    }
}

我希望你找到问题!

更新

调用此行时

Hibernate.initialize(vendorList.get(0).getVedorTechnologies()); 

我得到了这个例外

HibernateException: collection is not associated with any session

我认为OpenEntityManagerInViewFilter无效的意思。

1 个答案:

答案 0 :(得分:2)

我解决了这个问题。 缺少的是在控制器上方添加注释@Transactional

@Transactional
@Controller
@RequestMapping("/analysis")
public class Analysis {
@Resource
private VendorRepository vendorRepository;
@RequestMapping(value = "/vendors", method = RequestMethod.GET)
@ResponseBody
public String getVendors()
{
    List<Vendor> vendorList= vendorRepository.findAll();
    Hibernate.initialize(vendorList.get(0).getVedorTechnologies()); 
    return vendorList.get(0).getVedorTechnologies().get(0).getName();
}