2017-02-11 67 views
0

來自厄瓜多爾的問候:使用Hibernate +春季3個事務數據庫

目前我已經創建了我必須在3名不同的數據庫進行操作的項目。爲此,我決定使用Hibernate ORM 5.2.7,Spring Framework 4.3.6和其他庫來實現連接池等。春天的上下文的配置的實施支持我的註解,我在下面顯示:

@Configuration 
@ComponentScan("fttg.*") 
@EnableTransactionManagement 
@EnableScheduling 
@PropertySources({ 
     @PropertySource("classpath:application.properties"), 
     @PropertySource("classpath:schedule.properties") 
}) 
public class ApplicationConfig { 

     @Autowired 
     private Environment environment; 

@Bean(destroyMethod = "close") 
public BasicDataSource dataSourceBitacora() { 
    BasicDataSource dataSource = new BasicDataSource(); 
    dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver")); 
    dataSource.setUrl(environment.getRequiredProperty("bitacora.jdbc.url")); 
    dataSource.setUsername(environment.getRequiredProperty("bitacora.jdbc.username")); 
    dataSource.setPassword(environment.getRequiredProperty("bitacora.jdbc.password")); 
    dataSource.setPoolPreparedStatements(true); 
    dataSource.setInitialSize(4); 
    dataSource.setMaxTotal(4); 
    dataSource.setMaxIdle(2); 
    dataSource.setMinIdle(1); 
    dataSource.setDefaultAutoCommit(Boolean.FALSE); 
    return dataSource; 
} 

@Bean(destroyMethod = "close") 
public BasicDataSource dataSourceFacturacion() { 
    BasicDataSource dataSource = new BasicDataSource(); 
    dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver")); 
    dataSource.setUrl(environment.getRequiredProperty("facturacion.jdbc.url")); 
    dataSource.setUsername(environment.getRequiredProperty("facturacion.jdbc.username")); 
    dataSource.setPassword(environment.getRequiredProperty("facturacion.jdbc.password")); 
    dataSource.setPoolPreparedStatements(true); 
    dataSource.setInitialSize(1); 
    dataSource.setMaxTotal(4); 
    dataSource.setDefaultAutoCommit(Boolean.FALSE); 
    return dataSource; 
} 

@Bean(destroyMethod = "close") 
public BasicDataSource dataSourceSietab() { 
    BasicDataSource dataSource = new BasicDataSource(); 
    dataSource.setDriverClassName(environment.getRequiredProperty("postgres.jdbc.driver")); 
    dataSource.setUrl(environment.getRequiredProperty("sietab.jdbc.url")); 
    dataSource.setUsername(environment.getRequiredProperty("sietab.jdbc.username")); 
    dataSource.setPassword(environment.getRequiredProperty("sietab.jdbc.password")); 
    dataSource.setPoolPreparedStatements(true); 
    dataSource.setInitialSize(1); 
    dataSource.setMaxTotal(2); 
    dataSource.setDefaultAutoCommit(Boolean.FALSE); 
    return dataSource; 
} 

@Bean 
public LocalSessionFactoryBean sessionFactoryBitacora() { 
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
    sessionFactory.setDataSource(dataSourceBitacora()); 
    sessionFactory.setPackagesToScan(environment.getRequiredProperty("bitacora.sessionFactory.packagesToScan")); 
    Properties properties = new Properties(); 
    properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect")); 
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); 
    sessionFactory.setHibernateProperties(properties); 
    return sessionFactory; 
} 

@Bean 
public LocalSessionFactoryBean sessionFactoryFacturacion() { 
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
    sessionFactory.setDataSource(dataSourceFacturacion()); 
    sessionFactory.setPackagesToScan(environment.getRequiredProperty("facturacion.sessionFactory.packagesToScan")); 
    Properties properties = new Properties(); 
    properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect")); 
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); 
    sessionFactory.setHibernateProperties(properties); 
    return sessionFactory; 
} 

@Bean 
public LocalSessionFactoryBean sessionFactorySietab() { 
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
    sessionFactory.setDataSource(dataSourceSietab()); 
    sessionFactory.setPackagesToScan(environment.getRequiredProperty("sietab.sessionFactory.packagesToScan")); 
    Properties properties = new Properties(); 
    properties.put("hibernate.dialect", environment.getRequiredProperty("postgres.hibernate.dialect")); 
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); 
    sessionFactory.setHibernateProperties(properties); 
    return sessionFactory; 
} 

@Bean 
public HibernateTransactionManager transactionManagerBitacora() { 
    HibernateTransactionManager txManager = new HibernateTransactionManager(); 
    txManager.setSessionFactory(sessionFactoryBitacora().getObject()); 
    return txManager; 
} 

@Bean 
public HibernateTransactionManager transactionManagerFacturacion() { 
    HibernateTransactionManager txManager = new HibernateTransactionManager(); 
    txManager.setSessionFactory(sessionFactoryFacturacion().getObject()); 
    return txManager; 
} 

@Bean 
public HibernateTransactionManager transactionManagerSietab() { 
    HibernateTransactionManager txManager = new HibernateTransactionManager(); 
    txManager.setSessionFactory(sessionFactorySietab().getObject()); 
    return txManager; 
} 
} 

的DAOS配置是數據庫中的所有對象都相同:

@Repository 
public class BitacoraFacturasDetalleDao extends GenericDaoImpl<BitacoraFacturasDetalle, Integer>{ 

private final static Logger LOGGER = Logger.getLogger(BitacoraFacturasDetalleDao.class); 

@Qualifier("sessionFactoryBitacora") 
@Autowired 
private SessionFactory sessionFactory; 

public BitacoraFacturasDetalleDao() { 
    super(BitacoraFacturasDetalle.class); 
} 

public BitacoraFacturasDetalle findByEstablecimientoAndPuntoEmisionAndSecuencial(String establecimiento, String puntoEmision, String secuencial) { 
    LOGGER.info("evento findByEstablecimientoAndPuntoEmisionAndSecuencial"); 
    BitacoraFacturasDetalle ret = (BitacoraFacturasDetalle) getCurrentSession().createNamedQuery("BitacoraFacturasDetalle.findByEstablecimientoAndPuntoEmisionAndSecuencial").setParameter("establecimiento", establecimiento).setParameter("puntoEmision", puntoEmision).setParameter("secuencial", secuencial).uniqueResult(); 
    return ret; 
} 

    @Override 
    protected Session getCurrentSession() { 
     return this.sessionFactory.getCurrentSession(); 
    } 

} 

交易對象實現如下:

@Service("facturasService") 
@Transactional(value="transactionManagerFacturacion", readOnly = false) 
public class FacturasServiceImpl implements FacturasService, Serializable { 

private static final long serialVersionUID = 1L; 
private final static Logger LOGGER =  Logger.getLogger(FacturasServiceImpl.class); 

@Autowired 
private FacturasCabeceraDao facturasCabeceraDao; 

@Override 
public boolean save(FacturasCabecera factura) { 
    LOGGER.info("evento save"); 
    return facturasCabeceraDao.save(factura); 
} 

} 

@Service("bitacoraFacturasDetalleService") 
@Transactional(readOnly = false, value = "transactionManagerBitacora") 
public class BitacoraFacturasDetalleServiceImpl implements BitacoraFacturasDetalleService, Serializable { 

private static final long serialVersionUID = 1L; 
private final static Logger LOGGER = Logger.getLogger(BitacoraFacturasDetalleServiceImpl.class); 

@Autowired 
private BitacoraFacturasDetalleDao bitacoraFacturasDetalleDao; 

@Override 
public boolean save(BitacoraFacturasDetalle b) { 
    LOGGER.info("evento save"); 
    return bitacoraFacturasDetalleDao.save(b); 
} 

@Override 
public boolean edit(BitacoraFacturasDetalle b) { 
    LOGGER.info("evento edit"); 
    return bitacoraFacturasDetalleDao.edit(b); 
} 

@Override 
@Transactional(readOnly = true, value = "transactionManagerBitacora") 
public BitacoraFacturasDetalle findByEstablecimientoAndPuntoEmisionAndSecuencial(String establecimiento, String puntoEmision, String secuencial) { 
    LOGGER.info("evento findByEstablecimientoAndPuntoEmisionAndSecuencial"); 
    return bitacoraFacturasDetalleDao.findByEstablecimientoAndPuntoEmisionAndSecuencial(establecimiento, puntoEmision, secuencial); 
} 

} 

而且在實現石英服務我調用通過3種不同類型的服務: 我從數據庫中檢索信息,生成幾個xmls,在第二個數據庫中插入bitacora的記錄,如果此操作正確,我更新從第一個基礎檢索到的記錄狀態,然後在其上創建數字簽名生成的xmls如果這個動作正確執行,我在第二個數據庫的記錄中進行狀態更改,並插入兩個表類型第三個數據庫的主和細節

然後我用這個代碼調用:

@Service 
public class ScheduleService implements Serializable { 
     @Autowired 
     private LocalidadService localidadService; 
     @Autowired 
     private CooperativaService cooperativaService; 
     @Autowired 
     private BoletoTasaService boletoTasaService; 
     @Autowired 
     private BitacoraFacturasDetalleService bitacoraFacturasDetalleService; 
     @Autowired 
     private InformacionTributariaService informacionTributariaService; 
     @Autowired 
     private ClientesService clientesService; 
     @Autowired 
     private FacturasService facturasService; 

     @Scheduled(cron = "${schedule.cronExpresion}") 
     public void start() { 
      if(XMLUtil.generarXML(factura, XML_GENERADO)) { 
      LOGGER.info("XML para la factura " + SECUENCIAL_DOCUMENTO + " generado correctamente"); 
      //code that fills a javaBean 
      //Execution of service that inserts in the database # 2 
      if(bitacoraFacturasDetalleService.save(bitacoraFacturaDetalle)) { 
           LOGGER.info("Factura " + SECUENCIAL_DOCUMENTO + " registrada en bitacora correctamente"); 
       // object retrieved from database # 1 to be changed status not to be taken into account in future 
       tasa.setStatusFacturacionElectronica("P"); 
       if(boletoTasaService.update(tasa)) { 
       //Other post-upgrade operations 

      } 
     } 
    } 
} 

這種情況是,這段代碼一直工作到一定數量的寄存器(大約700或800的數據庫1),在下一個插入或更新diff erent基地代碼進入「休眠」狀態,在很多時間後再次運行

對於轉換到生產之前執行的測試,請複製3個數據庫,這些數據庫對於此場景而言沒有併發連接與他們交互的系統和/或界面。

我不知道「問題」的原因是:使用的編程代碼,定義事務對象的策略(我已閱讀並被建議使用JTA,但從我已閱讀的機制中僅使用該機制事務性線程[控制數據庫上的操作的服務]),或者如果由於其他應用程序與不同數據庫的表的配合而帶來此不便

如果彈簧配置有任何問題,請幫忙,交易服務的定義,或者如果您肯定需要爲此使用JTA。

有可能表明我曾經使用過這種方案,我有一個或幾個數據庫,從中我可以提取信息,只有一個數據庫可以插入,因此我沒有問題;另一方面,在給定的情況下寫入三個數據庫

回答

0

至於所描述的問題,很難準確地說出可能的錯誤。不過,我可以給你一些提示:

  1. 你根本沒有使用任何連接池。嘗試用HikariCP連接池替換BasicDataSource
  2. 而不是長時間運行的交易。嘗試將它分成大塊。使用Spring Integration來構建管道。每個數據庫事務一次只能處理一小部分數據。這樣,VACUUM比運行長時間運行的交易擁有更好的運行機會。
+0

我在想第三個數據庫只使用spring,第二個只使用hibernate,而第一個只使用jdbc。你怎麼看? –

+0

我不明白這一點。試着找出數據庫爲什麼卡住了。它必須等待某個鎖定,或者等待VACUUM過程。 –