Spring 无法写入JSON:无法初始化代理-无会话错误

Spring 无法写入JSON:无法初始化代理-无会话错误,spring,hibernate,spring-mvc,session,Spring,Hibernate,Spring Mvc,Session,我正在尝试使用spring和JackSon JSON创建REST服务 我的建议: @Override @SuppressWarnings("unchecked") public Users findByUserName(String username) { Users user = new Users(); session = getSessionFactory().openSession(); try {

我正在尝试使用spring和JackSon JSON创建REST服务

我的建议:

    @Override
    @SuppressWarnings("unchecked")
    public Users findByUserName(String username) {

        Users user = new Users();
        session = getSessionFactory().openSession();
        try {
            transaction = session.beginTransaction();
            if (!username.isEmpty() && username != null) {
                List<Users> users = new ArrayList<Users>();
                users = session.createQuery("from Users where username=?")
                        .setParameter(0, username)
                        .list();

                if (!users.isEmpty()) {
                    user = users.get(0);
                }

                transaction.commit();
            }
        } catch (HibernateException e) {

            if (transaction != null) {
                transaction.rollback();
            }

            e.printStackTrace();
        } finally {
            session.close();
        }

        return user;
    }
我得到一个错误:

HTTP状态500-无法写入JSON:无法初始化代理- 无会话(通过引用链: com.spring.example.entities.Users[“roles”]->com.enclaveit.brea.entities.roles\u$$\ ujvstd4\u2[“role”]; 嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:无法 初始化代理-无会话(通过引用链: com.enclaveit.brea.entities.Users[“roles”]->com.enclaveit.brea.entities.roles\u$\ ujvstd4\u2[“role”])

据我所知,因为会话在DAOImpl类中是关闭的,所以在控制器中会话不再存在,对吗?当我试图注释代码行
session.close()时然后网络工作正常,我可以接收Json。但是当一个会话无法关闭时是很危险的,对吗

寻找最佳解决方案

注:如果您需要更多信息,请告诉我

多谢各位

更新:

休眠配置文件:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- MySQL data source -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://192.168.10.116:3306/brea" />
        <property name="username" value="root" />
        <property name="password" value="brea@123" />
        <property name="maxActive" value="-1"/>
    </bean>
    <!-- If request parameter "targetUrl" is existed, then forward to this url --> 
    <!-- For update login form -->
    <bean id="savedRequestAwareAuthenticationSuccessHandler"
        class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <property name="targetUrlParameter" value="targetUrl" />
     </bean>
    <!-- Hibernate session factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>orm/Roles.hbm.xml</value>
                <value>orm/Users.hbm.xml</value>
                <value>orm/UsersInfo.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
            <prop key="hibernate.dialect">
                           org.hibernate.dialect.MySQL5Dialect
                        </prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="userDao" class="com.enclaveit.brea.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="myUserDetailsService" 
                class="com.enclaveit.brea.services.MyUserDetailsService">
        <property name="userDao" ref="userDao" />
    </bean>

    <tx:annotation-driven />

    <!-- MUST have transaction manager, using aop and aspects  -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="dataSource" ref="dataSource" />
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
        <tx:method name="get*" read-only="true" />
        <tx:method name="find*" read-only="true" />
        <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="userServicePointCut"
        expression="execution(* com.enclaveit.brea.services.*Service.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
    </aop:config>
</beans>

最快的解决方案是首先从服务中删除会话和事务处理代码,然后在代码中(以及配置中)用
@Transactional
替换它

@Override
@SuppressWarnings("unchecked")
@Transactional(readOnly="true")
public Users findByUserName(String username) {
    Session session = getSessionFactory().getCurrentSession();      
    return (Users) session
                    .createQuery("from Users where username=?")
                    .setParameter(0, username)
                    .uniqueResult();
}
还请注意,
session
的作用域应限定为“决不将
session
存储为实例变量”的方法。(想象一下,如果对
findByUserName
进行了10次当前调用,会发生什么情况,实例变量
session
会发生什么情况)

在您的配置中,启用注释驱动的事务管理。(假设您已经有了
HibernateTransactionManager
definedn!)


因为您使用的是Spring框架,所以请使用
声明性事务
管理,而不是
编程事务


我相信您的
用户
实体具有延迟加载的
角色
属性。您可以将其更改为立即加载(不可取),或者在DAO方法中,在会话关闭之前使用getter
user.getRole()
加载
角色
信息。

将代理注释添加到实体类中即可完成此任务

@Entity @Table(name="Country") @Proxy(lazy = false) public class Country {}

使用@Transactional并让spring处理事务添加完整的stacktrace请不要自己处理事务和会话。使用spring为您执行此操作。接下来,返回创建JSON响应所需的所有内容,或者使用
OpenSessionInViewFilter
保持会话打开,直到请求完成处理。然后您没有正确配置
OpenSessionInViewFilter
,或者没有正确实现该方法。请注意
getCurrentSession
而不是
openSession
!。或者您的hibernate配置错误,并且没有与Springs Tx管理正确集成。请将hibernate配置添加到您的问题中。是否存在问题是否还有其他保持延迟加载的选择?在DAO方法中是的,在会话关闭之前,使用getter(类似于user.getRole())加载角色信息。
@Override
@SuppressWarnings("unchecked")
@Transactional(readOnly="true")
public Users findByUserName(String username) {
    Session session = getSessionFactory().getCurrentSession();      
    return (Users) session
                    .createQuery("from Users where username=?")
                    .setParameter(0, username)
                    .uniqueResult();
}
<tx:annotation-driven />
<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <!-- Replace with hibernate3, hibernate4 or hibernate5 depending on the hibernate version one uses -->
</filter>

<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <servlet-name>dispatcher</servlet-name> <!-- name of your DispatcherServlet -->
</filter-mapping>
@Entity @Table(name="Country") @Proxy(lazy = false) public class Country {}