2016-09-04 100 views
1

同事們,你能幫我用@Transactional註釋。我的目標是將DB事務管理傳遞給Spring,並且在當前情況下將數據保存在DB中。爲什麼我使用@Transactional註釋時數據未保存?

我在DAO類兩種方法:

@Component 
    public class OdValuesDAO 
    { 


      static final Logger LOG = 

Logger.getLogger(OdValuesDAO.class.getName()); 
     @Autowired 
     // @PersistenceContext(unitName = "PersistenceUnit") 
     @Qualifier("emR") 
     private EntityManager em; 
    public void addOdValue (OdValuesEntity odValuesEntity) { 
     LOG.info(odValuesEntity.toString()); 
     //EntityTransaction tx = em.getTransaction(); Data will be saved DB if uncomment this code. 
     ///tx.begin(); 
     //LOG.info(tx.isActive()); 
     em.persist(odValuesEntity); 
     ///tx.commit(); 

    } 


    public List<OdValuesEntity> getShare (OdValuesEntity odValuesEntity) { 
     CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriaQuery<OdValuesEntity> criteriaQuery = cb.createQuery(OdValuesEntity.class); 
     Root<OdValuesEntity> entityRoot = criteriaQuery.from(OdValuesEntity.class); 

     Predicate criteria = cb.conjunction(); 
     if (odValuesEntity.getId() != null) ......... 

     criteriaQuery.where(criteria); 
     List<OdValuesEntity> result = em.createQuery(criteriaQuery).getResultList(); 

     return result; 

    } 

和服務方法:

@Component 
    public class OdValuesService { 

     static final Logger LOG = Logger.getLogger(OdValuesService.class.getName()); 

     @Autowired 
     private OdValuesDAO odValuesDAO; 

    /** 
    * Read data from table. 
    * @param odValuesEntity 
    * @return 
    */ 

    @Transactional (readOnly = true, value = "txtxManagerR") 
    public List<OdValuesEntity> getShare (OdValuesEntity odValuesEntity) { 
     odValuesDAO.getShare(odValuesEntity); 
     return odValuesDAO.getShare(odValuesEntity); 

    } 
    /** Add record to the table 
    */ 
    @Transactional (value = "txtxManagerR") /*I have two transaction managers for two different DataSources/ 
    public void addOdValue (OdValuesEntity odValuesEntity) { 
     odValuesDAO.addOdValue(odValuesEntity); 
    } 

} 

而且我有一個測試,調用這兩個方法。我可以使用getShare方法從表中讀取數據。但調用方法addOdValue後沒有保存數據。這是我的問題。 當我取消註釋addOdValue中的交易相關代碼時,一切正常。正如我在這種情況下所理解的,Spring事務管理器不起作用。

如何糾正addOdValue方法,或者可能是,使用Spring @Transactional註釋將spring配置文件保存在數據庫中(以打開和提交事務)?

我的Spring配置(上下文)包含下一豆DB工作:

@Configuration 
@EnableBatchProcessing 
@EnableTransactionManagement 
@ComponentScan 
public class AppConfig { 

    @Bean 
    public BasicDataSource specRDataSource() { 
     BasicDataSource specRDataSource = new BasicDataSource(); 
     specRDataSource.setDriverClassName("org.firebirdsql.jdbc.FBDriver"); 
     specRDataSource.setUrl(specRDbUrl); 
     specRDataSource.setUsername(specRDbUser); 
     specRDataSource.setPassword(specRDbPassword); 
     specRDataSource.setMaxIdle(30); 
     specRDataSource.setMaxWaitMillis(10000); 
     specRDataSource.setValidationQuery("select 1 from rdb$database"); 
     specRDataSource.setTestOnBorrow(false); 
     specRDataSource.setTestWhileIdle(true); 
     specRDataSource.setDefaultAutoCommit(true); 

     return specRDataSource; 
    } 



    @Bean 
    public BasicDataSource bortDataSource() { 
     BasicDataSource bortDataSource = new BasicDataSource(); 
     bortDataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 
     bortDataSource.setUrl(bortDbUrl); 
     bortDataSource.setUsername(bortDbUser); 
     bortDataSource.setPassword(bortDbPassword); 
     bortDataSource.setMaxIdle(2); 
     bortDataSource.setMaxWaitMillis(10000); 
     bortDataSource.setValidationQuery("select 1"); 
     bortDataSource.setTestOnBorrow(true); 
     bortDataSource.setTestWhileIdle(true); 
     bortDataSource.setDefaultAutoCommit(true); 
     return bortDataSource; 
    } 



    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory (BasicDataSource bortDataSource) { 
     LocalContainerEntityManagerFactoryBean localConnectionFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
     localConnectionFactoryBean.setPersistenceXmlLocation("classpath:META-INF/persistence.xml"); 
     localConnectionFactoryBean.setDataSource(bortDataSource); 
     localConnectionFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
     return localConnectionFactoryBean; 
    } 


    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySpec (BasicDataSource specRDataSource) { 
     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setPersistenceXmlLocation("classpath:META-INF/persistence.xml"); 
     emf.setDataSource(specRDataSource); 
     Map<String, Object> properties = new HashMap<String, Object>(); 
     properties.put("hibernate.dialect", "org.hibernate.dialect.FirebirdDialect"); 
     emf.setJpaPropertyMap(properties); 
     HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); 
     hibernateJpaVendorAdapter.setGenerateDdl(true); 
     hibernateJpaVendorAdapter.setShowSql(true); 
     emf.setJpaVendorAdapter(hibernateJpaVendorAdapter); 

     return emf; 
    } 


    @Bean 
    public EntityManager emR (@Qualifier("entityManagerFactorySpec") EntityManagerFactory entityManagerFactorySpec) { 
     return entityManagerFactorySpec.createEntityManager(); 
    } 


    @Bean 
    public EntityManager embort (@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) { 
     return entityManagerFactory.createEntityManager(); 
    } 




    @Bean 
    public JpaTransactionManager txtxManagerR (@Qualifier("entityManagerFactorySpec") EntityManagerFactory entityManagerFactorySpec) { 
     JpaTransactionManager txManager = new JpaTransactionManager(); 
     txManager.setEntityManagerFactory(entityManagerFactorySpec); 
     return txManager; 
    } 


    @Bean 
    public JpaTransactionManager txManagerbort (@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) { 
     JpaTransactionManager txManager = new JpaTransactionManager(); 
     txManager.setEntityManagerFactory(entityManagerFactory); 
     return txManager; 
    } 

} 

我的persistence.xml樣子(如果需要):

<persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <class>com.acap.app.JpaEntities.OdDocsEntity</class> 
     <class>com.acap.app.JpaEntities.OdValuesEntity</class> 
    ....... 
     <class>com.acap.app.JpaEntities.OdOSharesEntity</class> 
     <properties> 
      <property name="hibernate.connection.url" 
         value="connection string"/> 
      <property name="hibernate.connection.driver_class" value="org.firebirdsql.jdbc.FBDriver"/> 
      <property name="hibernate.connection.username"/> 
      <property name="hibernate.connection.password"/> 
      <property name = "hibernate.show_sql" value = "false" /> 
      <property name = "hibernate.format_sql" value = "false" /> 
     </properties> 

    </persistence-unit> 

堆棧跟蹤不顯示任何錯誤。感謝您的幫助。

UPDATE 試運行:

@RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) 
    public class OdValuesServiceTest { 
      static final Logger LOG = Logger.getLogger(OdValuesServiceTest.class.getName()); 

      @Autowired 
      OdValuesService odValuesService; 
      @Autowired 
      DBCommonsService dbCommonsService; 

@Commit  
@Test 
      public void addOdValue() throws Exception { 

       OdValuesEntity odValuesEntity = new OdValuesEntity(); 
       odValuesEntity.setId(dbCommonsService.getNextDocOD("OD_VALUES_ID_GEN")); 
       odValuesEntity.setSysname("Name" + DataGenerator.getRandomISIN()); 
       odValuesEntity.setName("Name"); 
       odValuesEntity.setIsIn((short) 1); 
       odValuesEntity.setvType(2); 
       odValuesEntity.setMfu((short) 0); 
       odValuesEntity.setIsin("AU000A0JP922"); 
       odValuesEntity.setCfi(""); 
       odValuesService.addOdValue(odValuesEntity); 
      } 
     } 
+1

代碼爲'odValuesDAO.addOdValue(odValuesEntity);'plz – Antoniossss

+0

@Antoniossss,我添加了對問題主體的更新。謝謝。 – May12

+0

刪除'EntityManager'的'@ Bean'聲明,你必須用'@ PersistenceContext'注入entitymanager,而不是'@ Autowired'注入。 –

回答

1

spring documentation

15.2.3事務管理

[..]默認情況下,該框架將創建和捲回交易 每次測試。[..]

所以,如果您的「問題」是,沒有數據使用@Transactional時寫到你的測試數據庫中,那麼這是一點問題都沒有,這是怎麼樣的春天默認工作。如果這不是你想要的...

如果你想有一個事務提交 - 不尋常的,但偶爾有用 當你想要一個特定的測試或修改 數據庫 - TestContext框架可以被指示導致 交易提交而不是通過@Commit註釋回滾。

+0

弗洛裏安,謝謝。我在測試方法中添加了註釋'@Commit @ Test',但數據仍未保存。 – May12

+0

你的測試不是事務性的,所以增加'@ Commit'不會做任何事情(只有當你的測試是'@ Transactional'時)。 –

+0

我將@ Transactional註解添加到了@ Test,並且有新的異常java.lang.IllegalStateException:要使用默認的BatchConfigurer,上下文必須包含不超過一個DataSource,找到2'。我需要限定數據源bean還是要做什麼? – May12

相關問題