简体   繁体   English

为什么我坚持不会发生什么?

[英]Why nothing happens when I persist?

I hope I does not ask a question you already answered, but I am not able to understand my problem... I explain : 我希望我不会问你已经回答的问题,但我无法理解我的问题...我解释说:

I work with Spring and Hibernate, I have a Manager interface, and a Manager that implements my interface. 我使用Spring和Hibernate,我有一个Manager接口,以及一个实现我的界面的Manager。 Manager is like this : 经理是这样的:

@Service
@Transactional
public class ManagerImpl implements Manager {
    @PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName="Service")
    private EntityManager em;

    public void storeHistoricMessage(...params...) throws DBException{
        HistoricMessage historicMessage = new HistoricMessage(); 
        // ... initialization of historicMessage
        try {
            em.persist(historicMessage);
        }
        catch (Exception e){
            // process the exception if exists... 
        }
    }
}

I call my service like this : 我这样称呼我的服务:

@Service
public class OtherManager {
    @Autowired
    private Manager manager;

    public void storeHistoricMessage(...params...) {
        manager.storeHistoricMessage(...params...);
    }
}

My application context is defined like this : 我的应用程序上下文定义如下:

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

    <context:component-scan base-package="package" />

    <bean id="JDBCPropertyConfigurer_service"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties" ref="JDBCProperties_service" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>

    <bean id="JDBCProperties_service"
        class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" value="classpath:jdbc.properties" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager_service"/>

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

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

    <!-- JPA config -->
    <bean id="entityManagerFactory_service"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource_service" />
        <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
        <property name="persistenceUnitName" value="Service" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--
                    <property name="generateDdl" value="${jpa.generateDdl}" />
                    <property name="showSql" value="${jpa.showSql}" /> <property
                    name="hbm2ddl.auto" value="${jpa.hbm2ddl}" />
                -->
            </bean>
        </property>
    </bean>

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

And Finally, my persistence.xml is like this : 最后,我的persistence.xml是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">

    <persistence-unit name="Service" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>package.HistoricMessage</class>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
            <property name="hibernate.archive.autodetection" value="class, hbm" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}" />
        </properties>
    </persistence-unit> 
</persistence>

The problem is that when I persist, nothing happens : no insert in database, no error message, no exception.... I made a lot of tests, and I have perhaps some helps : 问题是,当我坚持,没有任何反应:没有插入数据库,没有错误信息,没有异常......我做了很多测试,我也许有一些帮助:

  • If I try to get back my object with em.find(), I get it... cache optimization ? 如果我尝试用em.find()取回我的对象​​,我得到它...缓存优化?
  • If I trap it, and rename table in database after start service, I have no error, he is always happy... 如果我捕获它,并在启动服务后重命名数据库中的表,我没有错误,他总是很高兴...
  • If I try em.flush(), it throws a Exception because no transaction is in progress... 如果我尝试em.flush(),它会抛出异常,因为没有进行任何事务...

Finally, here are TRACE logs I can see : 最后,这里是我可以看到的TRACE日志:

DEBUG 12-01 10:50:01,362 (SessionImpl.java:<init>:220)  -opened session at timestamp: 13263618013
DEBUG 12-01 10:50:01,362 (JDBCTransaction.java:begin:54)  -begin
DEBUG 12-01 10:50:01,362 (ConnectionManager.java:openConnection:421)  -opening JDBC connection
DEBUG 12-01 10:50:01,363 (DriverManagerDataSource.java:getConnectionFromDriver:163)  -Creating new JDBC DriverManager Connection to [jdbc:mysql://databaseurl]
DEBUG 12-01 10:50:01,378 (JDBCTransaction.java:begin:59)  -current autocommit status: true
DEBUG 12-01 10:50:01,379 (JDBCTransaction.java:begin:62)  -disabling autocommit
TRACE 12-01 10:50:01,380 (JDBCContext.java:afterTransactionBegin:214)  -after transaction begin
DEBUG 12-01 10:50:01,380 (JpaTransactionManager.java:doBegin:348)  -Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle: com.mysql.jdbc.JDBC4Connection@1ff335bb]
TRACE 12-01 10:50:01,381 (TransactionSynchronizationManager.java:bindResource:186)  -Bound value [org.springframework.jdbc.datasource.ConnectionHolder@184c9860] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@65499154] to thread [http-8001-Processor5]
TRACE 12-01 10:50:01,381 (TransactionSynchronizationManager.java:bindResource:186)  -Bound value [org.springframework.orm.jpa.EntityManagerHolder@4ca7d316] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@28ce2c57] to thread [http-8001-Processor5]
TRACE 12-01 10:50:01,381 (TransactionSynchronizationManager.java:initSynchronization:261)  -Initializing transaction synchronization
TRACE 12-01 10:50:01,382 (TransactionAspectSupport.java:prepareTransactionInfo:290)  -Getting transaction for [package.storeHistoricMessage]
storeHistoricMessage (begin of my function)
DEBUG 12-01 10:50:01,382 (EntityManagerFactoryUtils.java:doGetTransactionalEntityManager:194)  -Opening JPA EntityManager
DEBUG 12-01 10:50:01,388 (EntityManagerFactoryUtils.java:doGetTransactionalEntityManager:199)  -Registering transaction synchronization for JPA EntityManager
DEBUG 12-01 10:50:01,389 (SessionImpl.java:<init>:220)  -opened session at timestamp: 13263618013
TRACE 12-01 10:50:01,392 (TransactionSynchronizationManager.java:bindResource:186)  -Bound value [org.springframework.orm.jpa.EntityManagerHolder@69851576] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@20442c19] to thread [http-8001-Processor5]
TRACE 12-01 10:50:01,393 (IdentifierValue.java:isUnsaved:77)  -id unsaved-value strategy UNDEFINED
TRACE 12-01 10:50:01,394 (AbstractSaveEventListener.java:getEntityState:514)  -transient instance of: package.HistoricMessage
TRACE 12-01 10:50:01,394 (DefaultPersistEventListener.java:entityIsTransient:124)  -saving transient instance
DEBUG 12-01 10:50:01,397 (AbstractSaveEventListener.java:saveWithGeneratedId:112)  -generated identifier: ***identifier***, using strategy: org.hibernate.id.Assigned
TRACE 12-01 10:50:01,397 (AbstractSaveEventListener.java:performSave:153)  -saving [package.HistoricMessage#***identifier***]
end of my function
TRACE 12-01 10:50:01,399 (TransactionAspectSupport.java:commitTransactionAfterReturning:319)  -Completing transaction for [package.storeHistoricMessage]
TRACE 12-01 10:50:01,400 (AbstractPlatformTransactionManager.java:triggerBeforeCommit:903)  -Triggering beforeCommit synchronization
TRACE 12-01 10:50:01,400 (AbstractPlatformTransactionManager.java:triggerBeforeCompletion:916)  -Triggering beforeCompletion synchronization
TRACE 12-01 10:50:01,401 (TransactionSynchronizationManager.java:doUnbindResource:232)  -Removed value [org.springframework.orm.jpa.EntityManagerHolder@69851576] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@20442c19] from thread [http-8001-Processor5]
DEBUG 12-01 10:50:01,401 (EntityManagerFactoryUtils.java:closeEntityManager:313)  -Closing JPA EntityManager
TRACE 12-01 10:50:01,401 (SessionImpl.java:close:273)  -closing session
TRACE 12-01 10:50:01,402 (ConnectionManager.java:cleanup:375)  -connection already null in cleanup : no action
DEBUG 12-01 10:50:01,402 (AbstractPlatformTransactionManager.java:processCommit:730)  -Initiating transaction commit
DEBUG 12-01 10:50:01,402 (JpaTransactionManager.java:doCommit:451)  -Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@27b71c12]
DEBUG 12-01 10:50:01,403 (JDBCTransaction.java:commit:103)  -commit
TRACE 12-01 10:50:01,403 (SessionImpl.java:managedFlush:337)  -automatically flushing session
TRACE 12-01 10:50:01,403 (JDBCContext.java:beforeTransactionCompletion:205)  -before transaction completion
TRACE 12-01 10:50:01,404 (SessionImpl.java:beforeTransactionCompletion:393)  -before transaction completion
DEBUG 12-01 10:50:01,405 (JDBCTransaction.java:toggleAutoCommit:193)  -re-enabling autocommit
DEBUG 12-01 10:50:01,406 (JDBCTransaction.java:commit:116)  -committed JDBC Connection
TRACE 12-01 10:50:01,407 (JDBCContext.java:afterTransactionCompletion:219)  -after transaction completion
DEBUG 12-01 10:50:01,407 (ConnectionManager.java:aggressiveRelease:404)  -aggressively releasing JDBC connection
DEBUG 12-01 10:50:01,408 (ConnectionManager.java:closeConnection:441)  -releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
TRACE 12-01 10:50:01,408 (SessionImpl.java:afterTransactionCompletion:422)  -after transaction completion
TRACE 12-01 10:50:01,409 (AbstractPlatformTransactionManager.java:triggerAfterCommit:929)  -Triggering afterCommit synchronization
TRACE 12-01 10:50:01,409 (AbstractPlatformTransactionManager.java:triggerAfterCompletion:945)  -Triggering afterCompletion synchronization
TRACE 12-01 10:50:01,410 (TransactionSynchronizationManager.java:clearSynchronization:315)  -Clearing transaction synchronization
TRACE 12-01 10:50:01,410 (TransactionSynchronizationManager.java:doUnbindResource:232)  -Removed value [org.springframework.orm.jpa.EntityManagerHolder@4ca7d316] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@28ce2c57] from thread [http-8001-Processor5]
TRACE 12-01 10:50:01,410 (TransactionSynchronizationManager.java:doUnbindResource:232)  -Removed value [org.springframework.jdbc.datasource.ConnectionHolder@184c9860] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@65499154] from thread [http-8001-Processor5]
DEBUG 12-01 10:50:01,411 (JpaTransactionManager.java:doCleanupAfterCompletion:534)  -Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@27b71c12] after transaction
DEBUG 12-01 10:50:01,411 (EntityManagerFactoryUtils.java:closeEntityManager:313)  -Closing JPA EntityManager
TRACE 12-01 10:50:01,411 (SessionImpl.java:close:273)  -closing session
TRACE 12-01 10:50:01,412 (ConnectionManager.java:cleanup:375)  -connection already null in cleanup : no action

Thanks a lot for you help ! 非常感谢你的帮助!

Edit : I'm very sorry, I understood what happend and you wasn't able to find because I really simplified architecture of my project and I didn't tell you about the reason : In this project, I have several application-context files, and several datasources, so that I use several times.... And with Spring 2.5, you can have only one ! 编辑:我很抱歉,我理解发生了什么,你无法找到,因为我真的简化了我的项目的架构,我没有告诉你原因:在这个项目中,我有几个应用程序上下文文件和几个数据源,所以我使用了几次....而对于Spring 2.5,你只能有一个! So that I can't use transactions in my second service... To solve that, I used aop like this : 所以我不能在我的第二个服务中使用交易...为了解决这个问题,我使用了这样的aop:

<tx:advice id="txAdviceSelfCare" transaction-manager="transactionManager_service">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <!-- other methods use the default transaction settings (see below) -->
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="ServiceManagerOperations"
        expression="execution(* package.ServiceManager.*(..))" />
    <aop:advisor advice-ref="txAdviceService"
        pointcut-ref="ServiceManagerOperations" />
</aop:config>

<!-- a PlatformTransactionManager is still required -->
<bean id="transactionManager_service" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory_service" />
</bean>

Thanks all for your help ! 感谢你的帮助 !

could you try to inspect what really happens on your database ? 你能尝试检查数据库中真正发生的事情吗? Try to activate log facilities on that database and if you have such tool installed to sniff network traffic between your Java code and the database server ... it could be useful... You could ask your JPA layer to show SQL generated , it could give you interesting data... My 2 pieces jerome 尝试激活该数据库上的日志工具,如果安装了这样的工具来嗅探Java代码和数据库服务器之间的网络流量...它可能很有用......你可以要求你的JPA层显示生成的SQL,它可以给你有趣的数据...我的2件jerome

Change your catch block to do something and watch what it prints. 更改您的catch块以执行某些操作并查看其打印内容。

    try {
        em.persist(historicMessage);
    }
    catch (Exception e){
        e.printStackTrace(); // use a logger if available
    }

You can also change the below property to true to see what's going on. 您还可以将以下属性更改为true以查看正在发生的情况。

<property name="hibernate.show_sql" value="true" />

Also, make it a habit to trace method entry/exits using a suitable logging framework such as SLF4J . 此外,养成使用合适的日志框架(如SLF4J)跟踪方法进入/退出的习惯。

Note that the actual insert does not happen in the em.persist statement since the call is transactual, so your try/catch will not do much at all. 请注意,实际插入不会发生在em.persist语句中,因为调用是事务性的,所以你的try / catch根本不会做太多。 The actual persist is done when the transaction ends, which is when the service layer call is finished (after return from your method). 实际的持久化是在事务结束时完成的,即服务层调用完成时(从方法返回后)。 This knowledge is critical when debugging persistence. 调试持久性时,这些知识至关重要。

Verify the database where you are looking the details. 验证数据库在哪里查看详细信息。 The log clearly says that commit is done.. 日志清楚地表明提交已完成..

DEBUG 12-01 10:50:01,403 (JDBCTransaction.java:commit:103) -commit TRACE 12-01 10:50:01,403 (SessionImpl.java:managedFlush:337) -automatically flushing session TRACE 12-01 10:50:01,403 (JDBCContext.java:beforeTransactionCompletion:205) -before transaction completion TRACE 12-01 10:50:01,404 (SessionImpl.java:beforeTransactionCompletion:393) -before transaction completion DEBUG 12-01 10:50:01,405 (JDBCTransaction.java:toggleAutoCommit:193) -re-enabling autocommit DEBUG 12-01 10:50:01,406 (JDBCTransaction.java:commit:116) -committed JDBC Connection

Place your method call in try catch 将您的方法调用放在try catch中

public void storeHistoricMessage(...params...) {
    try {
       manager.storeHistoricMessage(...params...);
    } catch (Exception e) {
       e.printStackTrace(); // use a logger if available
    }
}

Data should be persisted at the end of manager.storeHistoricMessage method call (by transaction management proxy) not at em.persist call. 数据应该在manager.storeHistoricMessage方法调用(通过事务管理代理)结束时保留,而不是在em.persist调用。 You could also try em.flush: 你也可以试试em.flush:

try {
        em.persist(historicMessage);
        em.flush(); //force DB insert
    }...

It looks like you don't see an exception wich is thrown somwhere, problably by transacion manager. 看起来你并没有看到一个异常,因为交易经理可能会抛出这个异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM