Java 如何使用Spring批处理和Hibernate从@JoinColumn获取值 介绍

Java 如何使用Spring批处理和Hibernate从@JoinColumn获取值 介绍,java,spring,hibernate,jpa,spring-batch,Java,Spring,Hibernate,Jpa,Spring Batch,为了从数据库中提取一些数据,我正在尝试设置一个基本的hibernate和spring批处理项目。目标是提供一个查询(HQL),spring批处理应用程序基于此查询将所有数据提取到一个平面文件中 应用程序的一个要求是用户不必配置列的映射。因此,我试图创建一个DynamicRecordProcessor,它评估输入并将输入(例如表地址)传递给编写器,这样平面文件项编写器就可以使用passthroughFieldActor 在读取器-处理器-写入器xml配置下面: <!-- Standard S

为了从数据库中提取一些数据,我正在尝试设置一个基本的hibernate和spring批处理项目。目标是提供一个查询(HQL),spring批处理应用程序基于此查询将所有数据提取到一个平面文件中

应用程序的一个要求是用户不必配置列的映射。因此,我试图创建一个DynamicRecordProcessor,它评估输入并将输入(例如表地址)传递给编写器,这样平面文件项编写器就可以使用passthroughFieldActor

在读取器-处理器-写入器xml配置下面:

<!-- Standard Spring Hibernate Reader -->
<bean id="hibernateItemReader" class="org.springframework.batch.item.database.HibernateCursorItemReader">
    <property name="sessionFactory" ref="sessionFactory" />         
    <property name="queryString" value="from Address" />                
</bean> 

<!-- Custom Processor -->
<bean id="dynamicRecordProcessor" class="nl.sander.mieras.processor.DynamicRecordProcessor"/>   

<!-- Standard Spring Writer -->
<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
    <property name="resource" value="file:target/extract/output.txt" />  
    <property name="lineAggregator">
        <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
            <property name="delimiter" value="|"/>
            <property name="fieldExtractor">
                <bean class="org.springframework.batch.item.file.transform.PassThroughFieldExtractor"/>                                   
            </property>             
        </bean>
    </property>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
</bean>

<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
</bean> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"/>           
    <property name="cacheableMappingLocations" value="classpath*:META-INF/mappings/*.hbm.xml"/>    
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" lazy-init="true">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
以及城市中的相应列:

@Column(name="city_id", unique=true, nullable=false)
    public Short getCityId() {
        return this.cityId;
    }
使用
values.add(bw.getPropertyValue(propertyName))时当propertyName为“城市”时,发生以下异常:

org.hibernate.SessionException: proxies cannot be fetched by a stateless session
    at org.hibernate.internal.StatelessSessionImpl.immediateLoad(StatelessSessionImpl.java:292)
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:156)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:260)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
    at nl.sander.mieras.localhost.sakila.City_$$_jvstc2c_d.toString(City_$$_jvstc2c_d.java)
    at java.lang.String.valueOf(String.java:2982)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1132)
    at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1148)
    at nl.sander.mieras.processor.DynamicRecordProcessor.extract(DynamicRecordProcessor.java:52)
    at nl.sander.mieras.processor.DynamicRecordProcessor.process(DynamicRecordProcessor.java:27)
但是,该值可用,如下面的屏幕截图所示。

具体问题:如何获得300的值?

我已经尝试使用反射API获取值,但是我无法达到我想要获取的实际值

复制
我已经建立了一个公共回购协议。但是,您仍然需要一个本地数据库才能准确地再现问题。欢迎提出进一步隔离此问题的建议。

只需使用
useStatelessSession
属性将您的阅读器翻转为状态已满,而不是无状态:

<!-- Standard Spring Hibernate Reader -->
<bean id="hibernateItemReader" class="org.springframework.batch.item.database.HibernateCursorItemReader">
    <property name="sessionFactory" ref="sessionFactory" />         
    <property name="queryString" value="from Address" />
    <property name="useStatelessSession" value="false" />       
</bean> 


谢谢您的回答。不幸的是,您的解决方案创建了另一个错误
java.lang.NoSuchMethodError:org.hibernate.Session.close()Ljava/sql/Connection;org.springframework.batch.item.database.HibernateItemReaderHelper.close(HibernateItemReaderHelper.java:200)org.springframework.batch.item.database.hibernateCursorSoritemReader.doClose(HibernateCursorItemReader.java:229)
,这表明Spring和Hibernate之间可能存在依赖版本不匹配的情况。尝试将Hibernate版本降低到
4.3.11。最终版本非常好,谢谢!现在在我的输出文件中,实际对象被打印出来(nl.sander.mieras.localhost.sakila)。City@707865bd),这与根本不打印任何内容相比是一种改进。有点超出了这个问题的范围,但我还是要问;您知道如何从对象获取实际值(短值300)吗?在
City
类中重写默认的
toString()
方法
org.hibernate.SessionException: proxies cannot be fetched by a stateless session
    at org.hibernate.internal.StatelessSessionImpl.immediateLoad(StatelessSessionImpl.java:292)
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:156)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:260)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
    at nl.sander.mieras.localhost.sakila.City_$$_jvstc2c_d.toString(City_$$_jvstc2c_d.java)
    at java.lang.String.valueOf(String.java:2982)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1132)
    at org.springframework.util.StringUtils.collectionToDelimitedString(StringUtils.java:1148)
    at nl.sander.mieras.processor.DynamicRecordProcessor.extract(DynamicRecordProcessor.java:52)
    at nl.sander.mieras.processor.DynamicRecordProcessor.process(DynamicRecordProcessor.java:27)
<!-- Standard Spring Hibernate Reader -->
<bean id="hibernateItemReader" class="org.springframework.batch.item.database.HibernateCursorItemReader">
    <property name="sessionFactory" ref="sessionFactory" />         
    <property name="queryString" value="from Address" />
    <property name="useStatelessSession" value="false" />       
</bean>