Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring@Transaction无法使用LocalContainerEntityManager FactoryBean_Java_Sql Server_Spring_Hibernate_Transactions - Fatal编程技术网

Java Spring@Transaction无法使用LocalContainerEntityManager FactoryBean

Java Spring@Transaction无法使用LocalContainerEntityManager FactoryBean,java,sql-server,spring,hibernate,transactions,Java,Sql Server,Spring,Hibernate,Transactions,我正在开发一个应用程序,它接收各种XML文件,这些文件包含我存储在数据库中的不同“单个”对象。 目标是读取和处理所有文件。如果文件处理正确,它将移动到“已处理”文件夹。如果抛出异常,它将移动到错误文件夹 所需的行为是,如果其中一个文件中发生错误,所有文件都将回滚,数据库中不保存任何内容,所有文件都将复制到错误文件夹(以及已处理的文件) 文件夹的复制可能无法使用事务来完成,所以我手动执行 我的项目结构如下: 技术: Hibernate:3.5.0-Final 弹簧:3.1.1.释放 服务器:T

我正在开发一个应用程序,它接收各种XML文件,这些文件包含我存储在数据库中的不同“单个”对象。 目标是读取和处理所有文件。如果文件处理正确,它将移动到“已处理”文件夹。如果抛出异常,它将移动到错误文件夹

所需的行为是,如果其中一个文件中发生错误,所有文件都将回滚,数据库中不保存任何内容,所有文件都将复制到错误文件夹(以及已处理的文件)

文件夹的复制可能无法使用事务来完成,所以我手动执行

我的项目结构如下:

技术:

  • Hibernate:3.5.0-Final
  • 弹簧:3.1.1.释放
  • 服务器:Tomcat7
  • 数据库:SQL Server
我从一个观点开始,即交易的最佳地点是服务。我不添加传播属性,因为我需要默认属性。必需的行为:

@Transactional(rollbackFor = Exception.class)
private Feedback readIndividuals(File fileLocation) throws Exception {
    System.out.println("Start reading individuals");
    //Set the status of all database entries to DELETED
    individualEntityService.setAllStatussesToDeleted();
    }
    final File individualsProcessedFolder = new File(individualsProcessedFolderLocation);
    for (final File fileEntry : fileLocation.listFiles()) {
        if (fileEntry.isDirectory()) {
            readIndividuals(fileEntry, feedback);
         } else {
            individualReader.read(fileEntry.getAbsolutePath());
    ....
我在这里开始交易。individualReader是一个服务,它执行文件的实际读取和对数据库的写入

编辑 这里是我在EntityService中调用add方法的IndividualReader的代码:

 @Override
@Transactional
public void read(String fileLocation) throws Exception {

    JAXBContext jaxbContext = JAXBContext.newInstance(CDM.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

    XMLInputFactory factory = XMLInputFactory.newInstance();
    FileInputStream fileInputStream = new FileInputStream(fileLocation);
    XMLStreamReader xmlr = factory.createXMLStreamReader(fileInputStream, ENCODING);

    try {
        xmlr.nextTag();
        xmlr.require(XMLStreamConstants.START_ELEMENT, null, "CDM");

        xmlr.nextTag();
        while (xmlr.getEventType() == XMLStreamConstants.START_ELEMENT) {

            JAXBElement<CDM.Individual> jaxbIndividual = unmarshaller.unmarshal(xmlr,
                    CDM.Individual.class);
            CDM.Individual individual = jaxbIndividual.getValue();
            Individual individualDO = individualBuilder.build(individual);
            Set<Diploma> diplomas = diplomaBuilder.build(individual.getDiplomas(), individualDO);
            Set<HealthCareProfessional> healthCareProfessionals = healthCareProfessionalBuilder.build(individual.getHCProfessionals());
            individualDO.addHealthCareProfessionals(healthCareProfessionals);
            individualDO.addDiplomas(diplomas);
            LOG.debug("Adding individual with SSIN  [" + individualDO.getSsin() + "] into DB");
            Individual retrievedIndividual = individualEntityService.read(individualDO.getSsin());
            if (retrievedIndividual != null) {
                  individualEntityService.remove(retrievedIndividual);
                  individualDO.setStatus(EntryStatus.UPDATED);
            }
            individualEntityService.add(individualDO);
            LOG.debug("Individual with SSIN [" + individualDO.getSsin() + "] successfully added to DB");
            LOG.debug(getIndividualXMLAsString(individualDO));

            if (xmlr.getEventType() == XMLStreamConstants.CHARACTERS) {
                xmlr.next();
            }
        }
    } finally {
        xmlr.close();
        fileInputStream.close();
    }
}
@Override
@Transactional
public void add(Individual individual) {
    individualDao.addIndividual(individual);
}
这个类除了调用DAO之外什么都不做,我用@Transactional注释了它。由于默认值为Propagation.REQUIRED,因此它不会启动新的物理事务,但会加入服务的事务

最后是道:

@Transactional
public void addIndividual(Individual individual) {
    em.persist(individual);
} 
我还使用事务性注释这个方法,原因与上面相同。 实体管理器使用Spring在DAO中自动连接:

@PersistenceContext
private EntityManager em;
实体管理器在applicationContext中定义如下:

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="individual"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect"/>
            <property name="generateDdl" value="true"/>
            <property name="showSql" value="false"/>
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

org.hibernate.dialogue.sqlserverdialogue
现在,所有的编译和部署都很好,并且工作正常。但是,当我使其中一个XML文件在损坏的文件进入数据库之前损坏所有文件,并且事务不会回滚

我想我一定是遗漏了什么,我的错误可能是错误地使用了@Transaction和Spring EntityManager的组合。我从不使用显式em.flush()将数据推送到数据库。可能em.persist错误,将数据存储到数据库中,我无法从中恢复

有人知道我做错了什么吗?非常感谢您的帮助

编辑完整的上下文:

<?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:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/task
   http://www.springframework.org/schema/task/spring-task-3.0.xsd
   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">

<context:component-scan base-package="be.healthconnect.pwg" />
<task:annotation-driven />
<tx:annotation-driven />

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>classpath:/be/healthconnect/pwg/core/properties/pwg.properties</value>
    </property>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close">
    <property name="driverClassName" value="${datasource.driver.class.name}" />
    <property name="url" value="${datasource.url}" />
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="individual"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect"/>
            <property name="generateDdl" value="true"/>
            <property name="showSql" value="false"/>
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="jpaVendorAdaptor"
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />

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

类路径:/be/healthconnect/pwg/core/properties/pwg.properties
org.hibernate.dialogue.sqlserverdialogue

我犯的错误如下:@Transactional注释无效,因为它注释了一个私有方法。代理生成器忽略了它

我在以下文件中找到了解决方案:

方法可见性和@Transactional

使用代理时,应仅将@Transactional注释应用于具有公共可见性的方法。 如果使用@Transactional注释对受保护的、私有的或包可见的方法进行注释,则不会引发错误,但注释的方法不会显示已配置的事务设置。如果需要注释非公开方法,请考虑使用AspectJ(见下文)。


您是否有
?是的,我已经在application-context.xml中指定了它,包括正确的命名空间定义请发布整个上下文。某些配置可能已关闭。已完成,我已将其添加到我的初始帖子中。我看不到您正在调用的
add
。造成这种情况的最可能原因是无意中跨越了某个事务边界。