使用Spring MVC 3和OpenSessionInViewFilter在我的应用程序中通过hibernate尝试更新对象大约需要5个小时而没有任何运气。
我可能已经浏览了StackOverflow和其他论坛中的所有可用线程!
Hibernate不会抛出任何错误,并说对象已更新,但它没有反映在我的数据库中。
任何帮助都会受到大力赞赏。
所以,这是我要更新的 JSON请求:
{
"id": "14",
"name": "Whatever",
"contactNumber": "918026754027",
"manager": "Vishwas", --> I've updated this value
"capacity": "222",
"addressId": "31",
"streetAddress": "1168, 1st Block, 17th Main, ABC",
"countryId": "1",
"stateId": "1",
"cityId": "1",
"area": "DEF",
"pincode": "560050"
}
控制器:
@RequestMapping(value = "/branches/update", method = RequestMethod.POST, headers = {"Content-Type=application/json"})
@ResponseBody
public Map<String, Object> updateBranch(@RequestBody Map<String, String> requestMap) {
boolean status = false;
boolean branchStatus = false;
Map<String, Object> statusMap = new HashMap<String, Object>();
Branch branch = new Branch();
Address address = new Address();
address.setId(Long.parseLong(requestMap.get("addressId")));
address.setCountry(countryService.getCountryById(Long.parseLong(requestMap.get("countryId"))));
address.setState(stateService.getStateById(Long.parseLong(requestMap.get("stateId"))));
address.setCity(cityService.getCityById(Long.parseLong(requestMap.get("cityId"))));
address.setType("BRANCH");
address.setArea(requestMap.get("area"));
address.setStreetAddress(requestMap.get("streetAddress"));
address.setPincode(requestMap.get("pincode"));
address.setModifiedBy("vishwas");
address.setModifiedTimestamp(new Date());
status = addressService.updateAddress(address);
if (status) {
branch.setId(Long.parseLong(requestMap.get("id")));
branch.setName(requestMap.get("name"));
branch.setAddress(address);
branch.setContactNumber(requestMap.get("contactNumber"));
branch.setManager(requestMap.get("manager"));
branch.setActive(true);
branch.setCapacity(Integer.parseInt(requestMap.get("capacity")));
branch.setModifiedTimestamp(new Date());
branch.setModifiedBy("vishwas");
branchStatus = branchService.updateBranch(branch);
}
if (branchStatus) {
statusMap.put("status", branchStatus);
statusMap.put("message", "Branch was updated successfully");
} else {
boolean delStatus = addressService.deleteAddress(address);
statusMap.put("status", branchStatus);
statusMap.put("message", "Problem updating branch. Please check with your system administrator");
}
return statusMap;
}
服务类:
@Service("branchService")
@Transactional
public class BranchServiceImpl implements BranchService {
@Autowired
private BranchDAO branchDAO;
private static Logger logger = Logger.getLogger(BranchService.class.getName());
public boolean updateBranch(Branch branch) {
logger.debug("Processing request to dao to update a branch --> " + branch.getId());
return branchDAO.updateBranch(branch);
}
}
DAO方法:
public boolean updateBranch(Branch branch) {
boolean status = false;
try {
logger.debug("Trying to update a branch --> " + branch.getId());
sessionFactory.getCurrentSession().update(branch);
status = true;
} catch (HibernateException exception) {
logger.error("Problem updating a branch --> " + exception.getMessage());
} catch (Exception exception) {
logger.error("Problem updating a branch --> " + exception.getMessage());
}
return status;
}
**更新2:正如Mr.Deinum所建议的那样,我已将事务管理器配置移动到o2-data.xml,现在只扫描调度程序中的控制器,同时扫描o2-data.xml中的其他组件
数据配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
">
<context:component-scan base-package="com.adwitiya.o2plus">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driverClass}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan">
<array>
<value>com.adwitiya.o2plus.model</value>
</array>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
</value>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
调度程序配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:component-scan base-package="com.adwitiya.o2plus">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven>
<mvc:message-converters>
<!-- Use the HibernateAware mapper instead of the default -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.adwitiya.o2plus.utilities.HibernateAwareObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:resources mapping="/gui/**" location="/gui/"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
</beans>
的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>O2 Plus</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/o2-data.xml
/WEB-INF/spring/o2-utils.xml
/WEB-INF/spring/o2-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>mySessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>o2-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/o2-dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>o2-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
答案 0 :(得分:2)
<context:component-scan base-package="com.adwitiya.o2plus" />
此<context:component-scan ... />
位于DispatcherServlet
。
<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:annotation-driven />
位于ContextLoaderLIstener
。
Bean(Factory)PostProcessor
仅对加载它的ApplicationContext
中的bean进行操作。它对父或子上下文中的bean没有任何作用。 <tx:annotation-driven />
注册一个由InfrastructureAdvisorAutoProxyCreator
BeanPostProcessor
处理的拦截器(或方面)。
将<tx:annotation-driven />
移至DispatcherServlet
的配置或修改组件扫描。 ContextLoaderListener
应扫描除@Controller
注释bean之外的任何内容,而DispatcherServlet
应仅扫描@Controller
注释bean。
ContextLoaderListener
配置。
<context:component-scan base-package="com.adwitiya.o2plus">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
DispatcherServlet
配置
<context:component-scan base-package="com.adwitiya.o2plus" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
答案 1 :(得分:1)
很明显,到目前为止,我已经想出解决这个问题的唯一方法是使用以下代码:
sessionFactory.getCurrentSession().flush();
让我们看看如何解决这个问题!
答案 2 :(得分:0)
确保您拥有:
@EnableTransactionManagement
并且Hibernate事务管理器知道您的会话工厂:
@Bean
public HibernateTransactionManager transactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
或
<tx:annotation-driven transaction-manager="txManager" />
如果您使用xml配置。
只要您使用基于Spring代理的故障拦截故障,就可以轻松调试服务层并检查Controller调用与实际服务方法之间TransactionInterceptor
的当前堆栈跟踪
如果你有TransactionInterceptor
,你应该使用事务,拦截器调用Hibernate事务。
您正在为新对象调用Session.update。合并是优先的,因为它适用于瞬态,分离和已附加的实例。
所以而不是:
sessionFactory.getCurrentSession().update(branch);
你应该:
sessionFactory.getCurrentSession().merge(branch);