现在我正在为智能平板制作RESTAPI项目。我正在使用Spring、Spring、Hibernate、MySql。现在我已经为用户创建了实体,当我尝试通过API检索用户时,我遇到了这样的异常:
无法写入JSON:无法初始化代理-没有会话;
我已经找到了解决办法如何防止这种异常的下一个链接
JsonMappingException:无法初始化代理-没有会话
@Proxy(懒=假)做什么?
@代理(懒=假)-已经解决了我的问题,但我真的不明白为什么当我尝试获取用户时,Spring控制器中的会话会关闭?
当我持久化用户时-没有这样的例外!尽管如此,相同的服务用于持久化和获取对象。怎么可能呢?
我的应用程序的逻辑是从web. xml开始的。我正在使用
org. Spring框架.web.ser v let.DispatcherS er v let
这个servlet将请求和传输映射到我的控制器。我正在使用Spring json消息转换器
org. Spring框架.http.转换器.json.映射Jackson 2 Http消息转换器
Spring的调度服务器的配置是
<mvc:annotation-driven/>
<context:component-scan base-package="com.smartcore.controllers.mysql"/>
<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
我的实体很简单,与其他实体没有任何关系
@Entity
@Table(name = "User")
//@Proxy(lazy = false)
public class UserMySql {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;
@Column(name = "email")
private String eMail;
@Column(name = "login")
private String login;
@Column(name = "password")
private String password;
public UserMySql() {}
public UserMySql(String name, String surname, String login, String password, String eMail) {
this.name = name;
this.surname = surname;
this.login = login;
this.password = password;
this.eMail = eMail;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String geteMail() {
return eMail;
}
public void seteMail(String eMail) {
this.eMail = eMail;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("UserMySql [id=");
sb.append(id);
sb.append(", name=");
sb.append(name);
sb.append(", surname=");
sb.append(surname);
sb.append(", eMail=");
sb.append(eMail);
sb.append(", login=");
sb.append(login);
sb.append(", password=");
sb.append(password);
sb.append("]");
return sb.toString();
}
控制器代码
@RestController
public class MySqlUserAccountController {
private UserMySqlService userMySqlService;
@Autowired
public MySqlUserAccountController( UserMySqlService userMySqlService) {
this.userMySqlService = userMySqlService;
};
@GetMapping("/user/{userId}")
public @ResponseBody UserMySql findUserById(@PathVariable("userId") Long userId) {
return userMySqlService.getUserById(userId);
}
@PostMapping("/user/add")
public void addUser(@RequestBody UserMySql user){
userMySqlService.save(user);
}
}
我正在使用Spring数据,它使用JpaRepository getOne(id)的原生方法来检索用户。
return this.userRepo.getOne(id);
我也找到了解决方法
org.springframework.orm.hibernate5.support. OpenSessionInViewFilter
但是配置过滤器和添加bean会话并没有帮助。
添加了web. xml
<servlet-mapping>
<servlet-name>dispServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
<!-- Replace with hibernate3, hibernate4 or hibernate5 depending on the
hibernate version one uses -->
</filter>
已添加应用程序上下文. xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.smartcore.entities.mysqldb"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
什么是最好的实现方式?如果使用@Proxy(懒=假)-导致从任何对象到我的对象的实时链接包含它,它会导致内存消耗增加吗?
在前面的回答中,我没有找到控制器中会话无效的原因。你能更详细地描述一下什么是原因吗?
更新
我仍然没有解决延迟加载的问题。我找到了这里描述的解决方案
http://blog.pastelstudios.com/2012/03/12/spring-3-1-hibernate-4-jackson-module-hibernate/
但在我的情况下,它不起作用,我不明白为什么?
web.xml config
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- Processes application requests -->
<servlet>
<servlet-name>dispServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
dispatcher-servlet.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="com.smartcore.controllers.mysql" />
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.smartcore.mappers.json.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
HibernateAware对象
public class HibernateAwareObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 5371945173448137189L;
public HibernateAwareObjectMapper() {
this.registerModule(new Hibernate5Module());
}
}
在日志中我没有看到我的自定义对象会被调用。它看起来像是带有配置的东西。
能有什么错?
您通过@Response sebody
返回一个对象,您返回的userObject是代理对象,因为您使用的是“LAZY”fetch。在控制器层,不再有活动事务来获取实体对象的属性。
您可以执行EAGER
获取对象或将子属性声明为瞬态
。