gpt4 book ai didi

java - Spring 3.2.1 + hibernate-core 4.2.0 : merge() not working

转载 作者:行者123 更新时间:2023-12-02 06:30:46 25 4
gpt4 key购买 nike

我开始使用 springapp 示例来学习 Spring 进行 Web 开发。现在,我试图提高列表中每个产品的价格(从数据库检索),然后将新价格保存回数据库。它可以检索产品列表,但合并不会执行任何操作。我将 .flush() 添加到代码中,它给出了一个丑陋的异常(只要应用程序启动)。

这是应用程序启动后抛出的异常(在调用 .flush() 方法之前):

javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:993)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:366)
at $Proxy18.flush(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
at $Proxy18.flush(Unknown Source)
at org.springtest.mavenspringapp.repository.JPAProductDao.saveProduct(JPAProductDao.java:34)
at org.springtest.mavenspringapp.service.SimpleProductManager.increasePrice(SimpleProductManager.java:35)
at org.springtest.mavenspringapp.web.PriceIncreaseFormController.onSubmit(PriceIncreaseFormController.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

这是一次我提高每种产品的价格并调用 .merge() ,然后调用 .flush() 的情况:

javax.persistence.TransactionRequiredException: no transaction is in progress
org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:993)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:366)
$Proxy18.flush(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
$Proxy18.flush(Unknown Source)
org.springtest.mavenspringapp.repository.JPAProductDao.saveProduct(JPAProductDao.java:34)
org.springtest.mavenspringapp.service.SimpleProductManager.increasePrice(SimpleProductManager.java:35)
org.springtest.mavenspringapp.web.PriceIncreaseFormController.onSubmit(PriceIncreaseFormController.java:38)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

这是 ProductDao:

@Repository(value = "productDao")
public class JPAProductDao implements ProductDao {

private EntityManager em = null;

/*
* Sets the entity manager.
*/
@PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}

@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Product> getProductList() {
return em.createQuery("select p from Product p").getResultList();
}

@Transactional(readOnly = false)
public void saveProduct(Product prod) {
em.merge(prod);
em.flush();
}

}

这是我的 Controller 中处理价格上涨表单的方法:

@RequestMapping(method = RequestMethod.POST)
public String onSubmit(@Valid PriceIncrease priceIncrease, BindingResult result)
{
if (result.hasErrors())
{
return "priceincrease";
}

int increase = priceIncrease.getPercentage();
logger.info("Increasing prices by " + increase + "%.");

productManager.increasePrice(increase);

return "redirect:/hello.htm";
}

ProductManager 是一项由名为 SimpleProductManager 的类实现的服务。此类更新每个产品的价格并尝试通过 JpaProductDao 将其保存到数据库。

这是我的 applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="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.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- holding properties for database connectivity /-->
<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- enabling annotation driven configuration /-->
<context:annotation-config/>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource"
p:jpaVendorAdapter-ref="jpaAdapter">
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
<property name="persistenceUnitName" value="springappPU"></property>
</bean>

<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="${jpa.database}"
p:showSql="${jpa.showSql}"/>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>

<!-- <tx:annotation-driven transaction-manager="transactionManager"/>-->
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

<context:component-scan base-package="org.springtest.mavenspringapp">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- Scans the classpath of this application for @Components to deploy as beans
<context:component-scan base-package="org.springtest.mavenspringapp.repository" />
<context:component-scan base-package="org.springtest.mavenspringapp.service" />
<context:component-scan base-package="org.springtest.mavenspringapp.web" />-->

</beans>

顺便说一句,我添加了 .flush 方法调用,因为有人在这里建议它(这是关于不持久更改的另一个问题)。

差点忘了,如果不包含 .flush(),产品就不会更新,也不会抛出异常。这是 hibernate 日志输出:

Hibernate: select product0_.id as id1_0_0_, product0_.description as descript2_0_0_, product0_.price as price3_0_0_ from products product0_ where product0_.id=?
Hibernate: select product0_.id as id1_0_0_, product0_.description as descript2_0_0_, product0_.price as price3_0_0_ from products product0_ where product0_.id=?
Hibernate: select product0_.id as id1_0_, product0_.description as descript2_0_, product0_.price as price3_0_ from products product0_

希望你能帮助我。提前致谢。

编辑:我正在发布我的 web.xml 文件内容:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<display-name>Mavenspringapp</display-name>

<servlet>
<servlet-name>mavenspringapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>mavenspringapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
</web-app>

应用程序配置.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>

<!-- Scans the classpath of this application for @Components to deploy as beans -->
<context:component-scan base-package="org.springtest.mavenspringapp" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>


<!-- Configures the @Controller programming model -->
<mvc:annotation-driven/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView">
</property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>

最佳答案

从堆栈跟踪来看,您加载了 Bean 两次,一次是由 ContextLoaderListener 加载的。其中已正确定义交易。一旦进入DispatcherServlet没有交易。 (你的堆栈跟踪没有显示 TransactionInterceptor 这让我相信这一点)。

确保您不会两次扫描相同的组件(不要在两个配置文件中重复 <context:component-scan /> 元素。

问题出在 app-config.xml 中的以下行

<context:component-scan base-package="org.springtest.mavenspringapp" />

再次创建所有bean的新实例,并且不会对其应用事务。 AOP 仅应用于定义 bean 的同一应用程序上下文中。所以基本上您有 JPAProductDao 的 2 个实例。一个(坐在那里无用)与交易以及 ApplicationContext 中未应用的内容由 ContextLoaderListener 加载ApplicationContext 中的另一个(未应用交易)由您的 DispatcherServlet 加载.

将组件扫描您的 applicationContext.xml 修改为以下内容

<context:component-scan base-package="org.springtest.mavenspringapp">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

并在您的 app-config.xml 中添加以下内容(注意:不要忘记 use-default-filters 属性!!!)

<context:component-scan base-package="org.springtest.mavenspringapp" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

您还可以删除 <context:annotation-config />使用 <context:component-scan /> 已经暗示了这一点。为您节省另一行 xml。

关于java - Spring 3.2.1 + hibernate-core 4.2.0 : merge() not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20078788/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com