2017-02-11 27 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过程。 –