0

我创建了一个示例 - SPRING、JPA(EclipseLink 持久性提供程序)和 JTA 事务管理器(JBoss 7)。我观察到数据库中的所有数据都在 UI 中正确显示以进行读取操作。但是当涉及到保存/更新或删除操作时,服务层并没有将工作提交给数据库。没有发现异常(我也检查了控制台/日志,还调试了我可以看到 entityManager.persist/remove 被调用的代码,没有任何异常)。

--代码清单-- 1.standalone.xml中的数据源配置

<datasource jta="true" jndi-name="java:/mysql_customerdb3" pool-name="mysql_customerdb3_pool" enabled="true" use-java-context="true" use-ccm="true">
            <connection-url>jdbc:mysql://localhost:3306/customerdb</connection-url>
            <driver>mysql</driver>
            <security>
                <user-name>root</user-name>
                <password>root</password>
            </security>
            <statement>
                <prepared-statement-cache-size>10</prepared-statement-cache-size>
                <share-prepared-statements>true</share-prepared-statements>
            </statement>
        </datasource>
        <drivers>
            <driver name="mysql" module="com.mysql">
                <driver-class>com.mysql.jdbc.Driver</driver-class>
    <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
            </driver>
            <driver name="h2" module="com.h2database.h2">
                <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
            </driver>
        </drivers>
  1. module.xml 中的数据库驱动配置

  2. 持久性.xml

    org.eclipse.persistence.jpa.PersistenceProvider java:/mysql_customerdb3 com.springforbeginners.model.Customer

  3. 客户调度程序-servlet.xml

    <context:annotation-config />
    <context:component-scan base-package="com.springforbeginners" />
    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="loadTimeWeaver" ref="loadTimeWeaver" />
        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
    </bean>
    
    <bean id="loadTimeWeaver" class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" >
    </bean>
    
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManagerName" value="java:jboss/TransactionManager"/>
        <property name="userTransactionName" value="java:jboss/UserTransaction"/>
    </bean> 
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    

  4. CustomerServiceImpl.java

    包 com.springforbeginners.service;

    导入 com.springforbeginners.dao.CustomerDAO;导入 com.springforbeginners.model.Customer;导入 java.util.List;导入 org.springframework.beans.factory.annotation.Autowired;导入 org.springframework.stereotype.Service;导入 org.springframework.transaction.annotation.Transactional;

    @Service 公共类 CustomerServiceImpl 实现 CustomerService { @Autowired private CustomerDAO customerDAO;

    @Transactional
    @Override
    public void addCustomer(Customer customer) {
        customerDAO.addCustomer(customer);
    }
    
    @Transactional
    @Override
    public List<Customer> listCustomer() {
        return customerDAO.listCustomer();
    }
    
    @Transactional
    @Override
    public void removeCustomer(Integer customerId) {
        customerDAO.removeCustomer(customerId);
    }
    

    }

  5. CustomerDAOImpl.java

    包 com.springforbeginners.dao;

    导入 com.springforbeginners.model.Customer;导入 java.util.List;导入 javax.persistence.EntityManager;导入 javax.persistence.PersistenceContext;导入 org.springframework.stereotype.Repository;

    @Repository 公共类 CustomerDAOImpl 实现 CustomerDAO { @PersistenceContext(unitName="CustomerDetailsPU3") private EntityManager entityManager;

    @Override
    public void addCustomer(Customer customer) {
        entityManager.persist(customer);
    }
    
    @Override
    public List<Customer> listCustomer() {
        return entityManager.createQuery("select c from Customer c", Customer.class).getResultList();
    }
    
    @Override
    public void removeCustomer(Integer customerId) {
        Customer customer = (Customer) entityManager.getReference(Customer.class, customerId);
        if (null != customer) {
            entityManager.remove(customer);
        }
    }
    

    }


我不知道究竟是什么以及在哪里丢失了一些东西。但是使用上面的代码,读取操作按预期工作。问题在于保存操作。我已将上面的示例转换为使用非 JTA 数据源(也为 jta=false 修改了standalone.xml)并使用 JpaTransactionManager 如下

使用非 JTA 数据源和 'org.springframework.orm.jpa.JpaTransactionManager' 所有操作(读取以及保存/更新/删除)都可以正常工作。

但是我的示例的 JTA 版本没有按预期工作(保存操作未将工作提交到数据库)。任何帮助/指针表示赞赏。

谢谢普拉卡什


詹姆士,

我将在 JBoss 上运行这个应用程序。但是 JBoss 上的一个数据源和 Glassfish 上的另一个数据源和事务应该同时跨越两个数据源的保存操作。这就是我想要达到的目标。我有一个 Web 应用程序,包括当前在 JBoss 上运行的服务(数据)层的 spring。

正如您之前所说,我将有两个persistence.xml,一个用于JBoss,一个用于Glassfish。当我第一次这样做时,我怀疑事务(跨越不同服务器上的两个数据源 - 在本例中为 JBoss 和 Glassfish)是否可以完全由 JBoss 执行(以防整个业务逻辑驻留在部署在 JBoss 上的 serviceImpl 类)?在这种情况下,我将使用 JBoss 事务管理器(property name="transactionManagerName" value="java:jboss/TransactionManager")。这是否足够,或者我是否也需要同样拥有 Glassfish 事务管理器?抱歉,如果这造成了混乱。

我的另一个问题是,是否有规定在persistence.xml/其他任何地方指定jndi 端口?(我肯定会有两个不同的persistence.xmls,我将在一个中提到目标服务器作为JBoss,在另一个中提到Glassfish)。

我们在春季是否有一种技术可以将业务逻辑分布在 JBoss/Glassfish 等不同的服务器上,并且仍然在一个单一的事务下?我不知道这是否可以选择。您是否在谈论这种情况,其中每个服务器需要两个不同的部署脚本?

谢谢普拉卡什

4

2 回答 2

2

你的persistence.xml是什么?

由于您使用的是 JTA,因此您必须定义“eclipselink.target-server”="JBoss"

于 2013-06-24T14:03:53.610 回答
1

我的 persistence.xml(modified) 现在如下所示。在 persistence.xml 中添加了目标服务器属性。这解决了问题。

  <persistence-unit name="CustomerDetailsPU3" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>java:/mysql_customerdb3</jta-data-source>
    <class>com.springforbeginners.model.Customer</class>
    <properties>
          <property name="eclipselink.target-server" value="JBoss" />
    </properties>
  </persistence-unit>

谢谢普拉卡什

于 2013-06-24T14:36:54.130 回答