Spring 无法写入JSON:无法初始化代理-无会话错误
我正在尝试使用spring和JackSon JSON创建REST服务 我的建议: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 {
@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方法中,在会话关闭之前使用getteruser.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 {}