Spring应用程序似乎不是持久数据 [英] Spring application doesn't appear to be persisting data

查看:90
本文介绍了Spring应用程序似乎不是持久数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在我的数据库中写入一些内容,但尽管它报告已成功完成请求,但仍无法正常工作。成功后,一切似乎都正常工作,并且我的控制器正确地重定向了我。



调试

  DEBUG adppayment.PaymentServiceImpl  - 请求保留新用户'max_test@test.com'。 
DEBUG a.d.p.payment.model.PaymentDAOImpl - 坚持com.app.payment.model.PaymentUser@86ceb985。
DEBUG osojSharedEntityManagerCreator $ SharedEntityManagerInvocationHandler - 为共享EntityManager调用创建新的EntityManager
DEBUG org.hibernate.impl.SessionImpl - 打开会话时间戳:13771737739
DEBUG ohedef.AbstractSaveEventListener - 延迟标识插入由于没有正在处理的事务
DEBUG osojpa.EntityManagerFactoryUtils - 关闭JPA EntityManager
DEBUG osbfsDefaultListableBeanFactory - 在名为'redirectForm'的Bean上调用afterPropertiesSet()$ b $ DE DEBUG osweb.servlet.DispatcherServlet - 渲染视图[org.springframework.web.servlet.view.JstlView:name'redirectForm'; DispatcherServlet中的URL [/WEB-INF/jsp/redirectForm.jsp],名称为'payment'
DEBUG osweb.servlet.view.JstlView - 转发到资源[/WEB-INF/jsp/redirectForm.jsp]在InternalResourceView中'redirectForm'
DEBUG osweb.servlet.DispatcherServlet - 成功完成请求

appContext.xml(根环境)

 < context:annotation-config /> 

< bean id =dataSource
class =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =usernamevalue =test/>
< property name =passwordvalue =test/>
< property name =driverClassNamevalue =com.mysql.jdbc.Driver/>
<! - payment_test是架构的名称 - >
< property name =urlvalue =jdbc:mysql://test1.com:3306 / payment_test/>
< / bean>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =persistenceUnitNamevalue =payment/>

< property name =persistenceUnitManager>
< bean class =org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager>
< property name =defaultDataSourceref =dataSource/>
< / bean>
< / property>

< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =showSqlvalue =true/>
< property name =generateDdlvalue =true/>
< property name =databasePlatformvalue =org.hibernate.dialect.MySQLDialect/>

< / bean>
< / property>
< / bean>

< context:component-scan base-package =com.app.payment/>
< context:annotation-config />

<! - 自动扫描组件 - >
< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager/>

< tx:annotation-driven />

PaymentUser

  @Entity 
@Table(name =PaymentUser)
public class PaymentUser {

@Id
@GeneratedValue
private int id;
...
}

PaymentService

  @Transactional(transactionManager)
@Service()
公共类PaymentServiceImpl实现PaymentService {

@Autowired
私人PaymentDAO paymentDAO;
// ...服务方法
}

付款DAO

  @Repository()
公共类PaymentDAOImpl实现PaymentDAO {

// @ PersistenceContext(unitName =payment)
@PersistenceContext()
EntityManager em;
}

好像它甚至不会启动交易。希望有足够的信息有人帮助我。感谢您的帮助。

更新



持久化(EntityManager em.persist())和删除( em.remove )不起作用。会不会有一个正确的问题。意思只是阅读权利而没有写权利,但在这种情况下,我应该会有一个错误。

更新2



在我的dataSource bean中添加了< aop:scoped-proxy /> ,但没有更改。就像我的debug msg所说的那样

  DEBUG ohedef.AbstractSaveEventListener  - 由于没有正在进行的事务而延迟标识插入

没有交易,但我的交易应在哪里开始?

我也检查了一些问题 Spring:Annotation驱动交易经理
,但我不知道该怎么做。

新appContext

 <?xml version =1.0编码= 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:jee =http://www.springframework.org/schema/jee
xmlns :tx =http://www.springframework.org/schema/tx
xmlns:aop =http://www.springframework.org/schema/aop
xsi:schemaLocation = http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/ aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema /beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd\">

< context:annotation-config />
< tx:annotation-driven />

<! - 自动扫描组件
< bean id =paymentDaoclass =com.app.payment.model.PaymentDAOImpl/>
< bean id =paymentServiceclass =com.app.payment.PaymentServiceImpl/>
应该做同样的
- >
< context:component-scan base-package =com.appn.payment/>

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


< bean id =dataSource
class =org.apache.commons.dbcp.BasicDataSourcelazy-init =falsedestroy-method =close >
< aop:scoped-proxy />
< property name =usernamevalue =user/>
< property name =passwordvalue =pw/>
< property name =driverClassNamevalue =com.mysql.jdbc.Driver/>
< property name =urlvalue =jdbc:mysql://test1.com:3306 / test/>
<! - < property name =testOnBorrowvalue =true/>
< property name =validationQueryvalue =SELECT 1/> - >
< / bean>

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactory
ref =entityManagerFactory/>
< / bean>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =persistenceUnitNamevalue =payment/>
< property name =dataSourceref =dataSource/>
< property name =persistenceUnitManager>
< bean class =org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager>
< property name =defaultDataSourceref =dataSource/>
< / bean>
< / property>

< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =showSqlvalue =true/>
< property name =generateDdlvalue =true/>
<! - < property name =databasePlatformvalue =org.hibernate.dialect.MySQL5InnoDBDialect/> - >
< property name =databasePlatformvalue =org.hibernate.dialect.MySQLDialect/>

< / bean>
< / property>

< property name =packagesToScanvalue =com.app.payment/>
< / bean>

< tx:annotation-driven />

< / beans>

更新3

试图在我的PaymentDAO em.flush()中刷新,这导致我出现错误消息。

 javax.persistence.TransactionRequiredException:没有事务在org.hibernate.ejb.AbstractEntityManagerImpl.flush中进行(AbstractEntityManagerImpl.java:792)

即:

  public void flush(){
if(!isTransactionInProgress()){
throw new TransactionRequiredException(no transaction is progress);
}
尝试{
getSession()。flush();
}
catch(RuntimeException e){
throw convert(e);
}
}

我需要某种特殊会话吗?
也记录在我的控制器中

  log.info(事务处于活动状态+ TransactionSynchronizationManager.isActualTransactionActive()) ; 

结果为false ...不知道为什么没有活动的交易...



UPDATE 4

  import java.util。清单; 

导入javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Repository
public class PaymentDAOImpl implements PaymentDAO {

private final Logger log = LoggerFactory.getLogger(getClass());


// @ PersistenceContext()
@PersistenceContext(unitName =payment)
EntityManager em;

@Override
public void persist(PaymentUser user){
log.debug(Persisting {}。,user);
em.persist(user);
//em.flush();


$ b @Override
public void remove(PaymentUser user){
log.debug(Removing {}。,user);
em.remove(user);
}

@Override
public List< PaymentUser> getPaymentUsers(){
log.debug(获取付款用户。);
return em.createQuery(FROM PaymentUser,PaymentUser.class).getResultList();

$ b @Override
public PaymentUser getPaymentUserById(String userId){
log.debug(获取id为{''',userId'的付款用户) ;
return em.createQuery(
FROM PaymentUser WHERE userId =:userId,PaymentUser.class)
.setParameter(userId,userId).getSingleResult();

$ b @Override
public void removePaymentUserById(String userId){
log.debug(删除ID为{''的付款用户。,userId) ;
em.createQuery(DELETE FROM PaymentUser WHERE userId =:userId,PaymentUser.class)。
setParameter(userId,userId).executeUpdate();


$ b @Override
public void mergePaymentUser(PaymentUser user){
log.debug(合并付款用户'{}'。,用户);
em.merge(user);
}
}

UPDATE 5 p>

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

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

<! - springapp servlet - >
< servlet>
< servlet-name>付款< / servlet-name>
< servlet-class> org.springframework.web.servlet.DispatcherServlet< / servlet-class>
1< / load-on-startup>
< / servlet>

< servlet-mapping>
< servlet-name>付款< / servlet-name>
< url-pattern> / payment / *< / url-pattern>
< url-pattern> / paymentExternalData< / url-pattern>
< url-pattern> / paymentInternalData< / url-pattern>
< / servlet-mapping>

<! - 欢迎文件 - >
< welcome-file-list>
< welcome-file> payment.jsp< / welcome-file>
< welcome-file> payment.html< / welcome-file>
< / welcome-file-list>

<! - S P R I N G - >

<! - 添加对Spring的支持 - >
<! - 默认applicationContext位置:/WEB-INF/applicationContext.xml - >


<! - UTF-8过滤器 - >
< filter>
< filter-name> characterEncodingFilter< / filter-name>
< filter-class> org.springframework.web.filter.CharacterEncodingFilter< / filter-class>
< init-param>
< / param-name>编码< / param-name>
< param-value> UTF-8< /参数值>
< / init-param>
< init-param>
< param-name> forceEncoding< / param-name>
< param-value> true< /参数值>
< / init-param>
< / filter>
< filter-mapping>
< filter-name> characterEncodingFilter< / filter-name>
< url-pattern> / *< / url-pattern>
< / filter-mapping>
< / web-app>

UPDATE 6



payment-servlet.xml

 <?xml version =1.0encoding =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:tx =http://www.springframework.org/schema/tx
xmlns :aop =http://www.springframework.org/schema/aop
xsi:schemaLocation =http://www.springframework.org/schema/aop http://www.springframework.org/ schema / aop / spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema / context http://www.springframework.org/schema/context/spring-context-3.1.xsd\">

< context:annotation-config />
< tx:annotation-driven />

<! - 自动扫描组件 - >
< context:component-scan base-package =com.app.payment/>

< bean id =viewResolverclass =org.springframework.web.servlet.view.InternalResourceViewResolver>
< property name =prefixvalue =/ WEB-INF / jsp //>
< property name =suffixvalue =。jsp/>
< / bean>

< / beans>

appContext.xml

 <?xml version =1.0encoding =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:tx =http://www.springframework.org/schema/tx
xmlns :aop =http://www.springframework.org/schema/aop
xsi:schemaLocation =http://www.springframework.org/schema/aop http://www.springframework.org/ schema / aop / spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema / context http://www.springframework.org/schema/context/spring-context-3.1.xsd\">

< context:annotation-config />
< tx:annotation-driven />

< bean id =dataSource
class =org.apache.commons.dbcp.BasicDataSourcelazy-init =falsedestroy-method =close>
< aop:scoped-proxy />
< property name =usernamevalue =test/>
< property name =passwordvalue =test/>
< property name =driverClassNamevalue =com.mysql.jdbc.Driver/>
< property name =urlvalue =jdbc:mysql://test1.com/test/>
< property name =testOnBorrowvalue =true/>
< property name =validationQueryvalue =SELECT 1/>
< / bean>

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactory
ref =entityManagerFactory/>
< / bean>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =persistenceUnitNamevalue =payment/>
< property name =dataSourceref =dataSource/>
< property name =persistenceUnitManager>
< bean class =org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager>
< property name =defaultDataSourceref =dataSource/>
< / bean>
< / property>

< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =showSqlvalue =true/>
< property name =generateDdlvalue =true/>
< property name =databasePlatformvalue =org.hibernate.dialect.MySQLDialect/>

< / bean>
< / property>
< / bean>

< / beans>


解决方案

确保您没有完全重复的< context:component-scan ... /> 元素。如果你有这个,你基本上复制了所有的bean实例。你最初得到的是所有的bean都被 ContextLoaderListener 加载,并且由于存在< tx:annotation-driven /> 。



现在如果您有相同的< context:component-scan ... /> 在您的payment-servlet.xml中,这将再次扫描所有创建另一个实例的bean,但是由于没有< tx:annotation-driven /> 它不会被代理,也不会被应用。



现在发生的事情是,只要你需要一个 @Service 带注释的bean DispatcherServlet 首先在它自己的 ApplicationContext 中查看是否存在是bean来满足它的需求。如果有的话将会被使用(你当前的情况),如果没有,它会查询父上下文(由 ContextLoaderListener 加载的)。



您需要配置 ContextLoaderListener 来扫描所有内容 @Controller 带注释的bean和 DispatcherServlet 来扫描用于 @Controller 带注释的bean。这可以通过正确配置< context:component-scan ... /> 来完成。



applicationContext.xml

 < context:component-scan base-package =com.appn.payment> 
< context:exclude-filter type =annotationexpression =org.springframework.stereotype.Controller/>
< / context:component-scan>

payment-servlet.xml

 < context:component-scan base-package =com.appn.paymentuse-default-filters =false> 
< context:include-filter type =annotationexpression =org.springframework.stereotype.Controller/>
< / context:component-scan>

这将为您提供事务并且只为您的bean提供单个实例。您应该从payment-servlet.xml文件中移除< tx:annotation-driven />



仍然有一个开放 JIRA问题,以使其包含在参考指南中。也是中的一个主题Spring社区论坛解释这一点。


I'm trying to write something into my database but it's not working despite it reporting "Successfully completed request". After the success everything seems to work fine and my controller redirects me correctly.

Debug

DEBUG a.d.p.payment.PaymentServiceImpl - Requesting to persist new user'max_test@test.com'.
DEBUG a.d.p.payment.model.PaymentDAOImpl - Persisting com.app.payment.model.PaymentUser@86ceb985.
DEBUG o.s.o.j.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation
DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13771737739
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'redirectForm'
DEBUG o.s.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'redirectForm'; URL [/WEB-INF/jsp/redirectForm.jsp]] in DispatcherServlet with name 'payment'
DEBUG o.s.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/jsp/redirectForm.jsp] in InternalResourceView 'redirectForm'
DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

appContext.xml (root context)

<context:annotation-config />

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="username" value="test" />
    <property name="password" value="test" />
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <!--payment_test is the name of the schema -->
    <property name="url" value="jdbc:mysql://test1.com:3306/payment_test" /> 
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="payment" />

    <property name="persistenceUnitManager">
        <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
            <property name="defaultDataSource" ref="dataSource" />  
        </bean>
     </property>

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

        </bean>
    </property>
</bean>

<context:component-scan base-package="com.app.payment" />
<context:annotation-config />

<!-- Auto scan the components -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />

<tx:annotation-driven />

PaymentUser

@Entity
@Table(name="PaymentUser")
public class PaymentUser {

    @Id
    @GeneratedValue
    private int id;
    ...    
}

PaymentService

@Transactional("transactionManager")
@Service()
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentDAO paymentDAO;
        // ... service methods
}

Payment DAO

@Repository()
public class PaymentDAOImpl implements PaymentDAO {

    //@PersistenceContext(unitName="payment")
    @PersistenceContext()
    EntityManager em;
}

It seems like it doesn't even start a transaction. Hope thats enough info for somebody to help me. Thanks for any help.

UPDATE

Getting data works fine. Persisting (EntityManager em.persist()) and removing ( em.remove ) are not working. Could there be a right problem. Meaning just read rights and no write rights, but in this case there should be an error i thought.

UPDATE 2

Added <aop:scoped-proxy /> to my dataSource bean, but no changes. Like my debug msg said

DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress

There is no transaction, but where should my transaction start?

I also checked issues Spring: Annotation-driven Transaction Manager but I'm not sure what to do.

New appContext

<?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:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- Auto scan the components 
            <bean id="paymentDao" class="com.app.payment.model.PaymentDAOImpl" />
            <bean id="paymentService" class="com.app.payment.PaymentServiceImpl" />
    should do the same      
    -->
    <context:component-scan base-package="com.appn.payment" /> 

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


    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" lazy-init="false" destroy-method="close"> 
        <aop:scoped-proxy />
        <property name="username" value="user" />
        <property name="password" value="pw" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://test1.com:3306/test" />
        <!--  <property name="testOnBorrow" value="true" />
        <property name="validationQuery" value="SELECT 1" />-->
    </bean>

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

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="payment" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
                <property name="defaultDataSource" ref="dataSource" />  
            </bean>
         </property>

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <!-- <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />  -->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

            </bean>
        </property>

        <property name="packagesToScan" value="com.app.payment" /> 
    </bean>

    <tx:annotation-driven />    

</beans>

UPDATE 3

Tried to flush in my PaymentDAO em.flush() which leads me to the error message.

javax.persistence.TransactionRequiredException: no transaction is in progress   at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:792)

which is:

public void flush() {
        if ( !isTransactionInProgress() ) {
            throw new TransactionRequiredException( "no transaction is in progress" );
        }
        try {
            getSession().flush();
        }
        catch ( RuntimeException e ) {
            throw convert( e );
        }
    }

Do i need some kind of special session ? Also logged it in my controller

log.info("Is transaction active " + TransactionSynchronizationManager.isActualTransactionActive());

which results to false... no sure why there is no active transaction...

UPDATE 4

import java.util.List;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Repository
public class PaymentDAOImpl implements PaymentDAO {

    private final Logger log = LoggerFactory.getLogger(getClass());


    //@PersistenceContext()
    @PersistenceContext(unitName="payment")
    EntityManager em;

    @Override
    public void persist(PaymentUser user) {
        log.debug("Persisting {}.", user);
        em.persist(user);
        //em.flush();

    }

    @Override
    public void remove(PaymentUser user) {
        log.debug("Removing {}.", user);
        em.remove(user);
    }

    @Override
    public List<PaymentUser> getPaymentUsers() {
        log.debug("Fetching payment users.");
        return em.createQuery("FROM PaymentUser", PaymentUser.class).getResultList();
    }

    @Override
    public PaymentUser getPaymentUserById(String userId) {
        log.debug("Fetching payment users with id '{}'.",userId);
        return em.createQuery(
                "FROM PaymentUser WHERE userId = :userId", PaymentUser.class)
                .setParameter("userId", userId).getSingleResult();
    }

    @Override
    public void removePaymentUserById(String userId) {
        log.debug("Removing payment users with id '{}'.",userId);
        em.createQuery("DELETE FROM PaymentUser WHERE userId = :userId ", PaymentUser.class).
        setParameter("userId", userId).executeUpdate();

    }

    @Override
    public void mergePaymentUser(PaymentUser user) {
        log.debug("Merging payment user '{}'.",user);
        em.merge(user);
    }
}

UPDATE 5

<?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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

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

        <!-- springapp servlet -->
    <servlet>
        <servlet-name>payment</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>payment</servlet-name>
          <url-pattern>/payment/*</url-pattern> 
          <url-pattern>/paymentExternalData</url-pattern>
        <url-pattern>/paymentInternalData</url-pattern> 
    </servlet-mapping>

    <!-- Welcome files -->
    <welcome-file-list>
         <welcome-file>payment.jsp</welcome-file>
         <welcome-file>payment.html</welcome-file>
    </welcome-file-list>

    <!-- S P R I N G -->

    <!-- Add Support for Spring -->
    <!-- Default applicationContext location: /WEB-INF/applicationContext.xml -->


    <!-- UTF-8 filter -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

UPDATE 6

payment-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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- Auto scan the components -->
    <context:component-scan base-package="com.app.payment" /> 

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

appContext.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:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" lazy-init="false" destroy-method="close"> 
        <aop:scoped-proxy />
        <property name="username" value="test" />
        <property name="password" value="test" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://test1.com/test" />
        <property name="testOnBorrow" value="true" />
        <property name="validationQuery" value="SELECT 1" />
    </bean>

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

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="payment" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
                <property name="defaultDataSource" ref="dataSource" />  
            </bean>
         </property>

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

            </bean>
        </property>
    </bean>

</beans>

解决方案

Make sure that you don't have exact duplicate <context:component-scan .../> elements in both xml configurations. If you have this you are basically duplicating all your bean instances. What you initially had was all beans get loaded by the ContextLoaderListener and those are proxied due to the existence of <tx:annotation-driven />.

Now if you have the same <context:component-scan .../> in your payment-servlet.xml this is going to scan again for all beans creating another instance, however due to the fact that there is no <tx:annotation-driven /> it will not be proxied and no transactions applied.

What now happens is that as soon as you need one of your @Service annotated beans the DispatcherServlet looks first in its own ApplicationContext to see if there is bean to satisfy its needs. If there is it is going to be used (your current case) if there isn't it will consult the parent context (the one loaded by the ContextLoaderListener).

What you need to do is configure the ContextLoaderListener to scan for everything BUT @Controller annotated beans and the DispatcherServlet to scan ONLY for @Controller annotated beans. This can be done by configuring the <context:component-scan .../> correctly.

applicationContext.xml

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

payment-servlet.xml

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

This will give you transactions and only single instances of your beans. You should remove the <tx:annotation-driven /> from the payment-servlet.xml file.

There is still an open JIRA issue to have this included in the reference guide. Also a thread in the Spring Community Forums explaining this.

这篇关于Spring应用程序似乎不是持久数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆