Spring 3.1 JPA在tomcat中运行时不插入数据

时间:2012-02-23 20:29:18

标签: spring transactions jpa-2.0

我花了三天时间试图找到这个问题的解决方案无济于事。我迫不及待地想出这个。我有一个简单的spring应用程序,运行在带有jstl标签1.2的servlet 2.5中,在带有spring 3.1的tomcat中运行,使用hibernate和hibernate jpa实现。

我可以列出页面中的数据,但我无法完成插入。记录可以追溯,似乎没有任何问题。然而,没有插入。我知道还有其他类似的帖子,但我已经仔细研究过它们并且无法在任何地方找到解决方案。

如果我通过MAIN类运行完全相同的代码,插入工作正常。它在tomcat中作为web-app运行时不起作用。

我试过通过main运行这个工作,在控制器内我跳过调用服务层,试图直接进入接口,当它没有工作时,我试着直接去实现DAO类,那个没工作。通过spring日志显示实体管理器正在创建,并在事务发生之前关闭。

请帮帮我。

这是我的App-context

            <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: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/context 
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" 
                    default-autowire="byName">

                <context:component-scan base-package="com.naturalbornliar.site"/>
                <tx:annotation-driven />
                <!-- Bean declarations go here-->

                <bean id="duke" class="com.naturalbornliar.site.entity.Admin">
                    <constructor-arg name="admin_id" type="Long" value="15" />
                    <constructor-arg name="admin_login" type="String" value="testUser" />
                    <constructor-arg name="admin_pwd" type="String" value="testPwd" />
                    <constructor-arg name="email_id" type="int" value="15" />
                    <constructor-arg name="quote" type="String" value="Something to say here" />    
                </bean>

            <!--    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> -->
            <!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"/> -->
            <!--        <property name="url" value="jdbc:mysql://localhost:3306/nbl_db"/> -->
            <!--        <property name="username" value="web_user"/> -->
            <!--        <property name="password" value="web_pwd"/> -->
            <!--        <property name="initialSize" value="5"/> -->
            <!--        <property name="maxActive" value="10"/> -->
            <!--    </bean> -->

                <bean id="simpledataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/nbl_db"/>
                    <property name="username" value="web_user"/>
                    <property name="password" value="web_pwd"/>
                </bean>

                <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                    <constructor-arg ref="simpledataSource"/>
                </bean>

                <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                    <property name="persistenceUnitName" value="nblPersistenceUnit"/>
                    <property name="dataSource" ref="simpledataSource"/>
                    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
                </bean>

            <!--    <bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> -->
            <!--        <property name="persistenceUnitName" value="nblPersistenceUnit"/> -->
            <!--        <property name="dataSource" ref="simpledataSource"/>-->
            <!--        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/> -->
            <!--    </bean> -->

                <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
                    <property name="entityManagerFactory" ref="emf"/>
                    <property name="jpaDialect" ref="jpaDialect"/>
                </bean>

                <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

                <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="database" value="MYSQL"/>
                    <property name="showSql" value="true"/>
                    <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                </bean>

                <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

                <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

                <tx:advice id="txAdvice">
                    <tx:attributes>
                        <tx:method name="add*" propagation="REQUIRED"/>
                        <tx:method name="delete*" propagation="REQUIRED"/>
                        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
                    </tx:attributes>
                </tx:advice>

                <aop:config>

                    <aop:advisor pointcut="execution(* *..CategoryDaoImpl.*(..))" advice-ref="txAdvice"/>

                </aop:config>

                </beans>

这是我的控制器:

            package com.naturalbornliar.site.mvc;

            import javax.inject.Inject;

            import org.apache.log4j.Logger;
            import org.springframework.stereotype.Controller;
            import org.springframework.ui.Model;
            import org.springframework.validation.BindingResult;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RequestMethod;

            import com.naturalbornliar.site.entity.Category;
            import com.naturalbornliar.site.entity.Link;
            import com.naturalbornliar.site.service.CategoryService;


            @Controller
            @RequestMapping("/categories")
            public class CategoryController {


                protected final Logger logger = Logger.getLogger(CategoryController.class);

                private final CategoryService categoryService;

                @Inject
                public CategoryController(CategoryService categoryService){
                    this.categoryService = categoryService;
                }

                @RequestMapping(value="/listCategories")
                public String listLinks(Model model){

                    model.addAttribute("categories", categoryService.getAllCategories());

                    return "categories";
                }

                @RequestMapping(method=RequestMethod.GET, params="new")
                public String showCreateCategoryForm(Model model){
                    model.addAttribute(new Category());
                    return "addcategory";
                }

                @RequestMapping(method=RequestMethod.POST)
                public String addCategoryFromForm(Category category, BindingResult bindingResult){
                    if(bindingResult.hasErrors()){
                        return"addcategory";
                        }
                    categoryService.addCategory(category);
                    return "redirect:/categories/listCategories";
                }
            }

这是我从控制器调用的服务:

            package com.naturalbornliar.site.service;

            import java.util.Collection;

            import javax.inject.Inject;

            import org.springframework.stereotype.Service;

            import com.naturalbornliar.site.entity.Category;
            import com.naturalbornliar.site.i.ICategoryDao;

            @Service
            public class CategoryService {

                private ICategoryDao iCategoryDao;

                @Inject
                public CategoryService(ICategoryDao iCategoryDao){
                    this.iCategoryDao = iCategoryDao;
                }

                public Collection<Category> getAllCategories(){
                    return iCategoryDao.getAllCategories();
                }

                public Collection<Category> getCategoriesByType(String type) {
                    return iCategoryDao.getCategoriesByType(type);
                }

                public Category getCategoryById(Long id) {
                    throw new UnsupportedOperationException();
                }

                public void deleteCategory(Category category) {
                    throw new UnsupportedOperationException();
                }

                public void updateCategory(Category category) {
                    throw new UnsupportedOperationException();
                }

                public void inactivateCategory(Category category){
                    throw new UnsupportedOperationException();
                }

                public void addCategory(Category category){
                    iCategoryDao.addCategory(category);
                }
            }

这是我的实施DAO:

            package com.naturalbornliar.site.dao;

            import java.util.Collection;
            import java.util.List;

            import javax.persistence.EntityManager;
            import javax.persistence.PersistenceContext;

            import org.apache.log4j.Logger;
            import org.springframework.stereotype.Repository;
            import org.springframework.transaction.annotation.Transactional;

            import com.naturalbornliar.site.entity.Content;
            import com.naturalbornliar.site.i.IContentDao;

            @Transactional
            @Repository
            public class ContentDaoImpl implements IContentDao {

                protected final Logger logger = Logger.getLogger(ContentDaoImpl.class);

                @PersistenceContext
                private EntityManager em;

                public EntityManager getEm() {
                    return em;
                }


                public void setEm(EntityManager em) {
                    this.em = em;
                }

                @Override
                public void addContent(Content content) {
                    // TODO Auto-generated method stub
                    em.persist(content);
                }

                @Override
                public void deleteContent(Content content) {
                    // TODO Auto-generated method stub
                    em.remove(content);

                }

                @Override
                public void inactivateContent(Content content) {
                    // TODO Auto-generated method stub

                }

                @Override
                public Content getContentById(Long id) {
                    // TODO Auto-generated method stub
                    return null;
                }

                @Override
                public Content getContentByName(String name) {
                    // TODO Auto-generated method stub
                    return null;
                }

                @Override
                public Collection<Content> getAllObjects() {
                    List<Content> resultList = em.createQuery("FROM Content", Content.class).getResultList();
                    return resultList;
                }

            }

这是界面(以防万一)

            package com.naturalbornliar.site.i;

            import java.util.Collection;

            import com.naturalbornliar.site.entity.Content;

            public interface IContentDao {

                public void addContent(Content content);
                public void deleteContent(Content content);
                public void inactivateContent(Content content);
                public Content getContentById(Long id);
                public Content getContentByName(String name);
                public Collection<Content> getAllObjects();

            }

4 个答案:

答案 0 :(得分:2)

杰里米,他可能会遇到很多问题而且我遇到了类似的问题。

在我的情况下,我使用了tomcat,我需要将spring weaver添加到tomcat(此问题在此处描述:http://asrijaffar.blogspot.com/2007/02/spring-jpa-tomcat.html)。

就我而言,我需要:

<tx:annotation-driven proxy-target-class="true" />

在DispatcherServlet配置中。

另外在db-context配置中:              

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="jpatest" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

答案 1 :(得分:2)

嗯,我实际上解决了这个问题。这是解决方案,还有另一个解决它的stackoverflow问题:

Spring @Transaction not starting transactions

基本上,正确触发交易所需要的只是我添加:

<tx:annotation-driven proxy-target-class="true"/>

到我的servlet xml。我想如果你只是在应用程序config.xml中使用它,它只能在主类下运行时(如独立),如果你需要在容器中运行它,你必须在servlet中声明事务注释。 / p>

答案 2 :(得分:0)

我还花了几个小时试图弄清楚问题出在哪里,虽然我之前使用相同堆栈的应用程序工作正常但我无法理解其中的差异。

并且....错误在spring-servlet.xml中的标记中 - 它被定义为使用所有Web控制器,存储库类等扫描根包。

更改它以仅使用网络控制器扫描包裹后,问题就消失了。

只为你(以及我),如果你遇到同样的问题,只需要一个额外的提示

答案 3 :(得分:0)

我也有同样的问题,花了几个晚上搜索 - 亚历克斯解决方案救了我 - 在servlet xml中我改变了上下文:组件扫描只扫描带有web控制器的包。 此页面中的示例应如下所示

<context:component-scan base-package="com.naturalbornliar.site.mvc"/>